.IIF DF,T$$APE $IDENT MUDRV,04,38, .IIF DF,D$$DSK $IDENT DUDRV,04,38, ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; ALL RIGHTS RESERVED. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; PREVIOUSLY MODIFIED BY: ; ; J. BERZLE, J. MELVIN, G. MARIGOWDA, P. WEISS ; M. NOEL, T. SCHOELLER, A. HUDED, D. CARROLL ; ; MODIFIED FOR RSX-11M-PLUS V4.6 BY: ; ; D. Carroll 29-Oct-1995 04.35 ; DC412 - Correct software writelock check on format, ; and include support for partitioned disks ; ; D. Carroll 03-Feb-1998 04.36 ; DC412 - Include support for extended LBN devices as ; part of partitioned disk support ; ; D. Carroll 13-Aug-1998 04.37 ; DC513 - Correct problem where PUCOM can be unmapped ; when doing shadow catchup on a higher level ; cached device. ; ; D. Carroll 29-Oct-1998 04.38 ; DC521 - Correct unit online (special case) to insure ; that GUS state is activated. ; ; ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,UCBDF$,SCBDF$,ABODF$,PKTDF$,UDADF$,KRBDF$ .MCALL QIOSY$,CLKDF$ QIOSY$ ABODF$ ; TKTN MESSAGES UDADF$ ; T/MSCP DEFINITIONS SCBDF$ ,,1 ; SCB DEFINITIONS HWDDF$ ; HARDWARE REGISTERS UCBDF$ ; UNIT CONTROL BLOCK OFFSETS PKTDF$ ; IOP DEFS KRBDF$ ; KRB OFFSET DEFINITIONS CLKDF$ ; CLOCK QUEUE DEFINITIONS JMPTBL PORT ; PORT ROUTINE OFFSETS ;+ ;DC412 ; Define where the flag byte will be for internal access ;DC412 ;- ;DC412 I.FLAG = I.PRM+11 ; use high order LBN info ;DC412 ;DC412 .IF DF D$$DSK ; disk I/O ;DC412 .IF DF D$$PRT!E$$LBN ; Partitions of 32-bit LBNs? ;DC412 I.FLAG = I.PRI ; use priority field instead ;DC412 .ENDC ;D$$PRT!E$$LBN ;DC412 .ENDC ;D$$DSK ; and disk I/O ;DC412 ;DC412 ; ; CHECK FOR THE PRE-ALLOCATED UMR WAIT BLOCKS. ; .IF DF D$$DSK .IF NDF DUUMR ; IF NO PRE-ALLO. UMR WAIT BLOCKS .ERROR DUUMR ; THEN REPORT ERROR .IFF ;DUUMR .IF GT ; PRE-ALLO. WAIT BLOCKS > MAXIMUM .ERROR DUUMR ; THEN REPORT ERROR .ENDC .ENDC ;DUUMR .IFF ;D$$DSK .IF NDF MUUMR ; IF NO PRE-ALLO. UMR WAIT BLOCKS DEFINED .ERROR MUUMR ; THEN REPORT ERROR .IFF ;MUUMR .IF GT ; PRE-ALLO. WAIT BLOCKS > MAX. WAIT BLOCKS .ERROR MUUMR ; THEN REPORT ERROR .ENDC .ENDC ;MUUMR .ENDC ;D$$DSK .PAGE .SBTTL JMPTAB - JUMP TABLE FOR VARIOUS CLASS ROUTINES ;=========================================================================== ; THE FOLLOWING JUMP TABLE --- MUST --- BE DEFINED AS THE FIRST THING ; WITHIN THIS MODULE. VARIOUS PORT DRIVERS EXPECT TO SEE THIS TABLE ; AT 120000. ; ; BE CAREFUL WHEN ADDING NEW ROUTINES TO ADD THEM TO THE END AND TO ALSO ; DEFINE THEM IN THE MACRO JMPTBL IN DSAPRE.MAC (WHICH CONTAINS THE OFFSET ; DEFINITIONS FOR THESE ROUTINES.) ;=========================================================================== XXBEGN::.WORD MAJOR*256.+MINOR ; COMPONENT ID (SET UP IN $IDENT MACRO) .WORD CLADAT ; DATAGRAM HANDLER .WORD CLAEND ; END PACKET HANDLER .WORD CLAERR ; PORT/CLASS ERROR HANDLER .WORD CLACMD ; T/MSCP COMMAND INITIATOR .WORD SCUCB ; SCAN UCB LIST .WORD CLASYN ; CLASS SYNCHRONIZATION .WORD -1 ; TERMINATOR ; ; LOCAL DATA ; EXEVEC: .WORD D.VINT ; FLAG FOR VECTOR NOT YET FILLED ; == 0 - IF BUILT WITH RSXVEC.STB ; <> 0 - IF BUILT WITH RSX11M.STB ALCLK: .WORD $ALCLK ALOCB: .WORD $ALOCB ALSEC: .WORD $ALSEC BLKC2: .WORD $BLKC2 BLXIO: .WORD $BLXIO CLINS: .WORD $CLINS CPURM: .WORD $CPURM CVLBN: .WORD $CVLBN DEACB: .WORD $DEACB DECLK: .WORD $DECLK DESEC: .WORD $DESEC DEUMR: .WORD $DEUMR DQUMR: .WORD $DQUMR DVMSG: .WORD $DVMSG .IF DF M$$PRO EXROP: .WORD $EXROP .ENDC ;DF M$$PRO EXRQF: .WORD $EXRQF FNERL: .WORD $FNERL FMSK6: .WORD $FMSK6 ;DC412 FORK1: .WORD $FORK1 GSPKT: .WORD $GSPKT IODSA: .WORD $IODSA IOFIN: .WORD $IOFIN LDREG: .WORD $LDREG LOGER: .WORD $LOGER MPPROR: .WORD $MPPRO MPUB1: .WORD $MPUB1 MULS: .WORD $$MUL .IF DF M$$PRO QFORK: .WORD $QFORK .ENDC ;DF M$$PRO QINSB: .WORD $QINSB QINSF: .WORD $QINSF QINSP: .WORD $QINSP QRMVA: .WORD $QRMVA RCTPT: .WORD $RCTPT SRNAM: .WORD $SRNAM SCERR: .WORD $SCERR SCOFL: .WORD $SCOFL STMP1: .WORD $STMP1 TKPS: .WORD $TKPS UMRWT: .WORD $UMRWT VOLVD: .WORD $VOLVD KISR5: .WORD KISAR5 KISR6: .WORD KISAR6 EXEVCL=<<<.-EXEVEC>/2>-1> LSTPKT:.WORD 0 ; LAST ABORTABLE IOP IN C.OLHD RADNAM:.WORD 0 ; PORT COMMON NAME IN RAD50 .RAD50 /OM/ ; END OF PORT COMMON NAME COMPCB:.WORD 0 ; STORAGE FOR PORT PCB ADDRESS SAVSTK:.WORD 0 ; SAVE STACK ADDRESS IN DELAYED ; CONTROLLER TRANSITION TO ONLINE .IIF DF D$$DSK&DU$CHK&D$$PRT .ERROR ; DU$CHK AND D$$PRT ;DC412 .IIF DF E$$LOG KEEPR1: .WORD 0 ; TO HOLD R1 DURING CLADAT CODE .IF DF,D$$DSK RSNEXP: .BLKW 18. ; TEMPORARY AREA FOR IO.RSN INFORMATION .ENDC ;D$$DSK CONTAB: .BYTE 0,0 ; DEFAULT ENTRY / UNKNOWN MODEL .IF DF,D$$DSK .BYTE RQDX3, ; NO SCSI ADAPTER, RQDX3 FORMAT STYLE .BYTE RQZX1, ; ROI SCSI ADAPTER / SPEC FORMAT STYLE .ENDC ;D$$DSK .IF DF,T$$APE .BYTE RQZX1, ; ROI SCSI ADAPTER .ENDC ;T$$APE CONEND: .BYTE 0,0 ; TABLE TERMINATOR. LEAVE THIS HERE!!! .PAGE .SBTTL IOFUN - I/O FUNCTION TRANSLATION TABLE IOFUN: .IF DF,D$$DSK FUNCT RLB,RD,RD.L,CMDRLB ; READ LOGICAL BLOCK FUNCT WLB,WR,WR.L,CMDWLB ; WRITE LOGICAL BLOCK .ENDC ;D$$DSK .IF DF,T$$APE FUNCT WLB,WR,WR.L,CMDWLB ; WRITE LOGICAL BLOCK FUNCT RLB,RD,RD.L,CMDRLB ; READ LOGICAL BLOCK FUNCT CMP,CMP,CMP.L,CMDCMP ; COMPARE HOST DATA .ENDC ;T$$APE .IF DF D$$DSK FUNCT LOV,RD,RD.L,CMDRLB ; LOAD OVERLAY FUNCT STC,AVL,AVL.L,CMDSTC ; SET DEVICE CHARACTERISTICS FUNCT RPB,RD,RD.L,CMDRPB ; READ PHYSICAL BLOCK ;DC412 FUNCT RLC,RD,RD.L,CMDRLB ; READ WITH READ CHECK ;**-1 FUNCT LDO,RD,RD.L,CMDRLB ; LOAD D SPACE OVERLAY FUNCT SCF,RD,RD.L,CMDRLB ; SHADOW CATCH UP FUNCT WPB,WR,WR.L,CMDWPB ; WRITE PHYSICAL BLOCK ;DC412 FUNCT WLC,WR,WR.L,CMDWLB ; WRITE WITH WRITE CHECK ;**-1 FUNCT WDD,WR,WR.L,CMDWDD ; WRITE WITH DELETED DATA MARK FUNCT INL,GUS,GUS.L,CMDGUS ; INITIALIZE (FOR RCT REPLACEMENT) FUNCT RPL,RPL,RPL.L,CMDRPL ; REPLACE BLOCK FUNCT RSN,0,0,CMDRSN ; READ SERIAL NUMBER FUNCT TRM,0,0,CMDTRM ; TERMINATE RCT PROCESSING FUNCT SMD,FMT,FMT.L,CMDFMT ; SET MEDIA DENSITY .IFF ;D$$DSK FUNCT EOF,WTM,WTM.L,CMDEOF ; WRITE EOF MARK FUNCT SPF,REP,REP.L,CMDSPF ; SPACE FILES FUNCT SPB,REP,REP.L,CMDSPB ; SPACE BLOCKS FUNCT RWD,REP,REP.L,CMDRWD ; REWIND UNIT FUNCT RWU,AVL,AVL.L,CMDRWU ; REWIND AND TURN UNIT OFFLINE FUNCT SMO,AVL,AVL.L,CMDSMO ; MOUNT AND SET TAPE CHARACTERISTICS FUNCT STC,ONL,ONL.L,CMDSTC ; SET CHARACTERISTICS FUNCT SEC,GUS,GUS.L,CMDGUS ; SENSE CHARACTERISTICS FUNCT DSE,ERS,ERS.L,CMDEOF ; ERASE (DATA SECURITY ERASE) FUNCT ERS,ERG,ERG.L,CMDEOF ; ERASE GAP FUNCT RLV,RD,RD.L,CMDRLV ; READ LOGICAL BLOCK REVERSE .ENDC ;D$$DSK EIOFUN: FUNCT 0,0,0,ILEGAL ; END OF TABLE (DISK/TAPE) ; ; FUNCTION TABLE ENTRIES FOR INTERNAL COMMANDS ; ONLFUN: FUNCT 0,ONL,ONL.L ; ONLINE T/MSCP COMMAND GUSFUN: FUNCT 0,GUS,GUS.L ; GET UNIT STATUS T/MSCP COMMAND ABOFUN: FUNCT 0,ABO,ABO.L ; ABORT T/MSCP COMMAND AVNFUN: FUNCT 0,AVL,AVL.L ; AVAILABLE T/MSCP COMMAND GCSFUN: FUNCT 0,GCS,GCS.L ; GET COMMAND STATUS T/MSCP COMMAND SCCFUN: FUNCT 0,SCC,SCC.L ; SET CONTROLER CHAR T/MSCP COMMAND .IF DF D$$DSK FMTFUN: FUNCT 0,FMT,FMT.L ; FORMAT COMMAND .ENDC ;D$$DSK .IF DF,T$$APE SNGDEN: .BYTE TK50 ; SINGLE DENSITY DRIVE/CONTROLLERS .BYTE TK70 .BYTE TZ30 .BYTE -1 ;TABLE TERMINATOR .EVEN .ENDC ;T$$APE ; ; TABLE FOR TRANSLATION OF MSCP END CODES TO RSX ERROR CODES ; RSXTAB: .BYTE IS.SUC ; 00 - SUCCESS .BYTE IE.IFC ; 01 - ILLEGAL FUNCTION CODE .BYTE IE.ABO ; 02 - COMMAND ABORTED .BYTE IE.DNR ; 03 - UNIT OFFLINE .BYTE IE.DNR ; 04 - UNIT AVAILABLE .IF DF D$$DSK .BYTE IE.BCC ; 05 - MEDIA FORMAT ERROR .IFF ; IF TAPE .BYTE IE.FHE ; 05 - UNDEFINED .ENDC ;D$$DSK .BYTE IE.WLK ; 06 - UNIT WRITE LOCKED .BYTE IE.CBE ; 07 - COMPARE ERROR .BYTE IE.VER ; 08 - DATA ERROR .BYTE IE.SPC ; 09 - HOST BUFFER ACCESS ERROR .BYTE IE.FHE ; 10 - CONTROLLER ERROR .BYTE IE.FHE ; 11 - DRIVE ERROR .IF DF T$$APE .BYTE IE.VER ; 12 - FORMATTER ERROR .BYTE IS.SUC ; 13 - BOT ENCOUNTERED .BYTE IE.EOF ; 14 - TAPEMARK ENCOUNTERED .BYTE IE.FHE ; 15 - UNDEFINED .BYTE IE.DAO ; 16 - RECORD DATA TRUNCATED .BYTE IE.VER ; 17 - POSITION LOST .BYTE IE.ABO ; 18 - SERIOUS EXCEPTION .BYTE IE.EOV ; 19 - LOGICAL END OF TAPE .IFF ;T$$APE .BYTE IE.FHE ; 12 - UNDEFINED .BYTE IE.FHE ; 13 - UNDEFINED .BYTE IE.FHE ; 14 - UNDEFINED .BYTE IE.FHE ; 15 - UNDEFINED .BYTE IE.FHE ; 16 - UNDEFINED .BYTE IE.FHE ; 17 - UNDEFINED .BYTE IE.FHE ; 18 - UNDEFINED .BYTE IE.FHE ; 19 - UNDEFINED .ENDC ;T$$APE .BYTE IE.FHE ; 20 - UNDEFINED .BYTE IE.FHE ; 21 - UNDEFINED .BYTE IE.FHE ; 22 - UNDEFINED .BYTE IE.FHE ; 23 - UNDEFINED .BYTE IE.FHE ; 24 - UNDEFINED .BYTE IE.FHE ; 25 - UNDEFINED .BYTE IE.FHE ; 26 - UNDEFINED .BYTE IE.FHE ; 27 - UNDEFINED .BYTE IE.FHE ; 28 - UNDEFINED .BYTE IE.FHE ; 29 - UNDEFINED .BYTE IE.FHE ; 30 - UNDEFINED .BYTE IE.FHE ; 31 - INTERNAL DIAGNOSTIC MESSAGE .EVEN ; ; DISK CLASS DRIVER DISPATCH TABLE ; .IF DF D$$DSK .IF DF DU$CHK ; QUEUE OPTIMIZATION SUPPORTED DDT$ DU,R$$UDA,,,,NEW=Y,OPT=Y; GENERATE DISPATCH TABLE .IFF ; DU$CHK DDT$ DU,R$$UDA,,,,NEW=Y ; GENERATE DISPATCH TABLE .ENDC ; DU$CHK ; ; TAPE CLASS DRIVER DISPATCH TABLE ; .IFF ;D$$DSK DDT$ MU,R$$MYA,,,,NEW=Y ; GENERATE DISPATCH TABLE .ENDC ;D$$DSK .PAGE .SBTTL XXINI - I/O INITIATOR ENTRY POINT ;+ ; **-MUINI-INITIATOR ENTRY POINT ; **-DUINI-INITIATOR ENTRY POINT ; ; INPUTS: ; ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2 = QST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ;- MUINI: DUINI: MOV S.QST(R4),R2 ; GET QST MOV S.PBIA(R4),@KISR6 ; MAP PORT DRIVER (IN APR 6) MOV S.PBIA(R4),@#KINAR6 ; KERNAL INSTRUCTION SPACE CALLR CLACMD ; TRY TO START A COMMAND .PAGE .SBTTL XXACC - PACKET ACCEPTANCE ROUTINE ;+ ; **-XXACC-ACCEPTANCE ROUTINE FOR $GSPKT ; ; THIS ROUTINE DECIDES WHICH PACKETS CAN BE PROCESSED. IT CHECKS UMR WAIT ; STATUS TO MAKE SURE THAT NECESSARY RESOURCES ARE AVAILABLE. IF THE UNIT IS ; IN SERIAL MODE, NO I/O'S FOR THAT DEVICE ARE PROCESSED. FOR DISKS, I/O MAY ; BE PREVENTED BY STALL I/O. FOR TAPES, IF ANY I/O'S ARE OUTSTANDING AND THE ; PACKET BEING CHECKED IS AN IO.SEC FUNCTION, THEN NO MORE PACKETS ARE ACCEPTED ; FOR THAT UNIT UNTIL ALL OUTSTANDING I/O'S COMPLETE (THIS IS TO INSURE THAT ; THE GUS TMSCP COMMAND, WHICH IS AN IMMEDIATE TYPE COMMAND, IS ISSUED TO A UNIT ; THAT IS QUIESCENT). THIS ROUTINE SHOULD ONLY BE CALLED FROM $GSPKT. ; ; INPUTS: ; ; R1 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0-R5 = PRESERVED ; C=1 = PACKET IS NOT TO BE DEQUEUED ; C=0 = PACKET IS TO BE DEQUEUED ;- XXACC: .IF DF D$$DSK BIT #UU.SER!UU.ATN!UU.IOS,U.UTIL(R5) ; SERIAL, ATTENTION, OR STALL BNE 40$ ; YES. GO REJECT PACKET BIT #UU.RCT,U.UTIL(R5) ; RCT IN PROGRESS ON THIS UNIT? BEQ 20$ ; NO CMP I.TCB(R1),@RCTPT ; YES. IS I/O FROM RCT? BNE 40$ ; NO. GO REJECT PACKET .IFF ;D$$DSK BIT #UU.SER!UU.ATN,U.UTIL(R5) ; ANY REASON NOT TO DO THIS I/O? BNE 40$ ; YES. GO REJECT PACKET CMP #IO.SEC,I.FCN(R1) ; SENSE CHARACTERISTICS COMMAND? BNE 20$ ; NO. CHECK FOR TRANSFER FUNCTION MOV S.QST(R4),R4 ; GET QST ASSUME Q.CST,0 MOV (R4),R4 ; GET CST TST C.OLHD(R4) ; OUTSTANDING COMMANDS? BNE 40$ ; YES. REJECT PACKET BR 30$ ; NO. ACCEPT PACKET .ENDC ;D$$DSK 20$: .IF NDF M$$PRO ; MIGHT NEED TO FORK IF WRONG PROCESSOR CMPB #IO.RLB/256.,I.FCN+1(R1); DATA TRANSFER REQUEST? BLO 30$ ; IF LO NO. ACCEPT THE PACKET BIT #DV.EXT,U.CW1(R5) ; IS EXTENDED MEMORY SUPPORTED? BNE 30$ ; YES. WE DON'T NEED UMRS .ENDC ;M$$PRO MOV S.QST(R4),R4 ; GET QST ASSUME Q.CST,0 MOV (R4),R4 ; GET CST BIT #C1.UMR,(R4) ; UNIT WAITING FOR UMRS? BNE 40$ ; YES. REJECT PACKET TST C.UMCT(R4) ; MORE UMR WAIT BLOCKS? BEQ 40$ ; NO. ; ; ACCEPT PACKET ; 30$: .IF DF,D$$DSK CMP I.TCB(R1),@RCTPT ; IS THE REQUEST FROM RCT...? BEQ 35$ ; IF EQ, DON'T CLEAR OUT UU.SEL BIC #UU.SEL,U.UTIL(R5) ; MAKE SURE ERROR PACKET LOGGING ON 35$: ; REFERENCE LABEL .ENDC ;D$$DSK MOV U.SCB(R5),R4 ; GET SCB CLC ; ACCEPT PACKET RETURN ; ; REJECT PACKET ; 40$: MOV U.SCB(R5),R4 ; GET SCB SEC ; REJECT PACKET RETURN .PAGE .SBTTL XXCAN - CANCEL I/O ENTRY POINT ;+ ; **-DUCAN-CANCEL I/O ENTRY POINT FOR DISK ; **-MUCAN-CANCEL I/O ENTRY POINT FOR TAPE ; ; THIS ROUTINE HANDLES ABORTING OUTSTANDING T/MSCP COMMANDS FOR A GIVEN ; TASK AND UNIT. FOR DISK, NO PROCESSING IS PERFORMED SINCE DISK I/O IS ; RELATIVELY FAST. FOR TAPE, THIS ROUTINE WILL STEP THROUGH THE OUTSTANDING ; I/O LIST AND SET A FLAG IN EACH PACKET THAT MATCHES THE UNIT AND TASK. ; LATER STATE PROCESSING WILL THEN STEP THROUGH THIS LIST AND ISSUE THE NEEDED ; ABORT COMMANDS. ; ; INPUTS: ; ; R0 = IOP ADDRESS ; R1 = TCB ADDRESS ; R3 = CONTROLLER INDEX ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0 = DESTROYED ; R1-R5 = PRESERVED ;- MUCAN: DUCAN: .IF DF,T$$APE CALL MAPD ; MAP PORT COMMON AREA THROUGH APR6 MOV S.QST(R4),R0 ; GET QST MOV (R0),R0 ; GET CST MOV R0,R2 ; GET WORK COPY MOV C.OLHD(R0),R0 ; GET FIRST IOP BEQ 30$ ; ALL DONE 10$: CMP I.TCB(R0),R1 ; IOP FOR CORRECT TASK? BNE 20$ ; NO. GET NEXT PACKET CMP I.UCB(R0),R5 ; IOP FOR CORRECT UNIT? BNE 20$ ; NO. GET NEXT PACKET BISB #IP.ABO,I.FLAG(R0) ; MARK IT FOR ABO COMMAND ISSUANCE ;DC412 BIS #C1.ABO,(R2) ; SET ABORT STATE FOR CONTROLLER ;**-1 BIT #UU.SER,U.UTIL(R5) ; ALREADY IN SERIAL MODE ON UNIT? BNE 20$ ; YES. DO NOT SAY WE SET IT BIS #UU.SER!UU.ABO,U.UTIL(R5); INDICATE SERIAL MODE AND WE SET IT 20$: MOV (R0),R0 ; GET NEXT IOP BNE 10$ ; CHECK IT 30$: BIT #C1.ABO,(R2) ; DID WE CHANGE STATES? BEQ 40$ ; IF EQ, NOPE CALLR MUINI ; GO PROCESS THE OPERATION 40$: .ENDC ;T$$APE RETURN .PAGE .IF DF D$$DSK&DU$CHK ; IF QUEUE OPTOMIZATION SUPPORTED .SBTTL XXCHK - DISK SEEK OPTIMIZATION CHECKING ; **-DUCHK-VALIDATE AND CONVERT THE LBN ; ; THIS ROUTINE IS CALLED FROM $DRQRQ TO DO LBN PROCESSING FOR DEVICES WHICH ; SUPPORT QUEUE OPTIMIZATION. IF BLKC2 DETECTS AN ERROR IT WILL RETURN TO THE ; CORRECT PLACE IN $DRQRQ AFTER CALLING $IOALT. ; ; INPUTS: ; ; R1 = IOP ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; IF THE CHECKS SUCCEEDS, THEN THE LBN IN THE PACKET ; IS REPLACED BY THE CYLINDER/TRACK/SECTOR. R1 IS PRESERVED. ; ; IF THE CHECKS FAILS, THEN $IOALT IS ENTERED WITH A FINAL ; STATUS OF IE.BLK AND A RETURN TO THE CORRECT PLACE IN ; $DRQRQ IS EXECUTED. ; ; NOTE: ALL FUNCTIONS PUT INTO THE DRIVER QUEUE ARRIVE HERE. ; THESE INCLUDE IO.ATT, IO.DET, AND ACP FUNCTIONS. ;- .ENABL LSB DUCHK: CMPB #IO.RLB/256.,I.FCN+1(R1); DATA TRANSFER REQUEST? BLO 30$ ; NO. LEAVE IT ALONE BITB #IO.RPB&IO.WPB,I.FCN(R1); READ/WRITE PHYSICAL BLOCK? BEQ 10$ ; NO. DO BLOCK CHECKING REQUE: MOV R1,R3 ; WE HAVE TO SIMULATE THE SETUP THAT CLRB I.FLAG(R3) ; BLKC2 WOULD PERFORM FOR $CVLBN ;DC412 MOV I.PRM+10(R3),R2 ; ... ;**-1 MOV I.PRM+12(R3),R0 ; ... BR 20$ ; NOW GO TO $CVLBN 10$: CALL @BLKC2 ; CHECK LOGICAL BLOCK NUMBER 20$: CALL @CVLBN ; CONVERT LOGICAL BLOCK NUMBER MOV R2,I.PRM+10(R3) ; SAVE DESIRED CYLINDER ADDRESS SWAB R1 ; SWAP TRACK TO HIGH BYTE BIS R1,R0 ; MERGE TRACK WITH SECTOR MOV R0,I.PRM+12(R3) ; SAVE DESIRED TRACK AND SECTOR ADDRESS MOV R3,R1 ; RESTORE PACKET ADDRESS 30$: RETURN .DSABL LSB .ENDC ;D$$DSK&DU$CHK .PAGE .SBTTL $XXINT - INTERRUPT HANDLER ;+ ; **-$XXINT-CLASS CONTROLLER INTERRUPT HANDLER ; ; INTERRUPTS ARE RECEIVED FROM A CONTROLLER UNDER FOUR CIRCUMSTANCES: ; 1. DURING THE INITIALIZATION PROCESS (OPEN THE "VIRTUAL CIRCUIT") ; 2. WHEN "COMMAND RING BUFFER" TRANSITIONS FROM "FULL" TO "NOT FULL" ; 3. WHEN "RESPONSE RING BUFFER" TRANSITIONS FROM "EMPTY" TO "NOT EMPTY" ; 4. WHEN A FATAL ERROR IS DETECTED AND AN INTERRUPT CAN BE GENERATED ;- .IF DF D$$DSK INTSE$ DU,PR5,R$$UDA ;;; GENERATE INTERRUPT SAVE CODE .IFF ;D$$DSK INTSE$ MU,PR5,R$$MYA ;;; GENERATE INTERRUPT SAVE CODE .ENDC ;D$$DSK ;;; R5 IS ANY UCB ON THE CONTROLLER ;;; R4 = CONTROLLER INDEX MOV U.SCB(R5),R4 ;;; POINT TO CONTROLLER STATUS BLOCK BIT #UU.SPC,U.UTIL(R5) ;;; SPECIAL ONLINE IN EFFECT? BEQ 10$ ;;; NO. FORK NORMALLY CALL SAVREG ;;; SAVE R0-R4 CALL MAPD ;;; MAP PORT DRIVER (IN APR 6) JMPV PORT,PORINT ;;; EXECUTE REQUEST AT PR5 10$: TST S.FRK+2(R4) ;;; FORK BLOCK IN USE? BEQ 20$ ;;; NO. CALL FORK RETURN ;;; YES. JUST RETURN 20$: MOV R4,S.FRK+6(R4) ;;; SAVE OUR CURRENT R4 ADD #S.FRK+6,R4 ;;; AND SET UP FOR CALL TO $FORK1 CALL @FORK1 ;;; CREATE SYSTEM PROCESS ;;; R5 MUST STILL BE THE UCB ;;; R4 MUST BE SCB BEFORE $FORK CALLED ; ; RETURN AT FORK STATE ; CLR S.FRK+2(R4) ; FREE FORK BLOCK FOR FURTHER INTERRUPTS MOV S.PBIA(R4),@KISR6 ; MAP PORT DRIVER (IN APR 6) MOV S.PBIA(R4),@#KINAR6 ; KERNAL INSTRUCTION SPACE JMPV PORT,PORINT ; TRANSFER TO PORT INTERRUPT ROUTINE .PAGE .SBTTL XXKRB - CONTROLLER STATE CHANGE ROUTINE ;+ ; **-XXKRB-CLASS CONTROLLER STATUS CHANGE ROUTINE ; ; THIS ROUTINE WILL HANDLE SETTING CONTROLLER ONLINE/OFFLINE REQUESTS. ; ; INPUTS ; ; R4 = DCB ADDRESS ; R3 = CTB ADDRESS ; R2 = KRB ADDRESS ; 0(SP) = RETURN ADDRESS FOR IMMEDIATE COMPLETION ; 2(SP) = RETURN ADDRESS FOR CALLER OF EXEC ROUTINE ; C = 1 TRANSITION TO OFFLINE REQUESTED ; C = 0 TRANSITION TO ONLINE REQUESTED ; $SCOFL NONZERO POSITIVE - SPECIAL ONLINE FOR SYSTEM DISK ; $SCERR = 1 PRESET TO SUCCESS ; PRIORITY = 0 ; ; OUTPUTS ; ; $SCERR = 0 OPERATION PENDING ; $SCERR < 0 OPERATION FAILED ($SCERR CONTAINS ERROR CODE) ; $SCERR = 1 OPERATION SUCCEEDED ; 0(SP) = RETURN ADDRESS OF CALLER OF $KRBSC ROUTINE ; ; THE DRIVER EITHER CHOSES TO REJECT THE STATUS REQUEST, ACCEPT IT IMMEDIATELY ; OR TO DO A DELAYED TRANSITION BY SAVING THE ADDRESS ON TOP OF THE STACK AND ; RETURNING TO THE SECOND ADDRESS ON THE STACK. ;- DUKRB:: MUKRB:: BCC 20$ ; IF CC, GO TRANSITION TO ONLINE MOV R2,R3 ; COPY KRB MOV K.OWN(R2),R4 ; GET UCB MOV U.SCB(R4),R4 ; GET SCB MOV S.QST(R4),R2 ; GET QST CALL MAPD ; MAP PORT DRIVER (IN APR 6) MOV COMPCB,R0 ; GET PCB OF PORT DRIVER DECB P.RMCT(R0) ; DECREMENT RESIDENT MAPPED TASK COUNT DEC 140000+CONCNT ; DECREMENT # OF CONTROLLERS USING PORT BNE 10$ ; IF NE, THERE ARE STILL MORE BIC #P2.LMA,P.ST2(R0) ; CLEAR THE 'LEAVE ME ALONE' BIT 10$: CALLV PORT,STOMP ; RESET CONTROLLER BIT #KS.EXT,K.STS(R3) ; CONTROLLER HAVE UMRS? BNE 60$ ; NO. FINISH UP MOV (R2),R3 ; GET CST SEC ; TELL PORUMR TO DEALLOCATE JMPV PORT,PORUMR ; DEALLOCATE UMRS AND EXIT ; ; TRANSITION TO ONLINE ; 20$: TST EXEVEC ; VECTORING DONE? BNE 22$ ; YES. PUSH ; SAVE REGISTERS MOV KINAR6,-(SP) ; SAVE KINAR6 MOV @#112,R0 ; GET ADDRESS OF TABLE OF ENTRIES MOV (R0),R0 ; GET ADDRESS OF APR BIAS MOV (R0),KINAR6 ; MAP COMMON THROUGH I-SPACE APR6 MOV #EXEVEC,R3 ; POINT TO VECTOR MOV #EXEVCL,R2 ; SPECIFY LENGTH OF VECTOR CALL @#140004 ; TRANSLATE VECTOR MOV (SP)+,KINAR6 ; RESTORE KINAR6 POP ; RESTORE REGISTERS 22$: CLR R5 ; NO BITS SET BISB K.HPU(R2),R5 ; GET ACTUAL UNIT NUMBER ASL R5 ; SHIFT TO WORD INDEX K.HPU*2 ADD R2,R5 ; ADJUST FOR KRB BASE R5 = KRB+(K.HPU*2) ADD K.OFF(R2),R5 ; R5 = LAST UCB SLOT IN KRB UCB TABLE MOV (R5),R5 ; R5 = UCB ADDRESS MOV U.SCB(R5),R4 ; GET SCB MOV R5,K.OWN(R2) ; GIVE K.OWN VALUE TSTB @SCOFL ; SPECIAL ONLINE? BLE 30$ ; NO. CONTINUE BIS #UU.SPC,U.UTIL(R5) ; SET SPECIAL ONLINE BIT IN UCB CLRB @SCERR ; CLEAR SCERR TO SHOW ONLINE PENDING BR 40$ ; DON'T DELAY RETURN FOR SPECIAL ONLINE 30$: POP ; DO DELAYED STATUS CHANGE 40$: .IIF DF D$$DSK MOV #VCDSK,R1 ; R1 = VIRTUAL CIRCUIT ID FOR DISK .IIF DF T$$APE MOV #VCTAP,R1 ; R1 = VIRTUAL CIRCUIT ID FOR TAPE CALL CLASUP ; INITIAL LOAD FUNCTIONS ON PORT COMMON BCS 50$ ; ERROR. GO HANDLE IT CALL MAPD ; MAP PORT DRIVER (IN APR 6) INC 140000+CONCNT ; INCREMENT # OF CONTROLLERS USING PORT MOV MPPROR,140000+MPPROX ; REVECTORED $MPPRO ADDRESS ; PUCOM CAN VECTOR OTHER ROUTINES CALLV PORT,PORSUP ; MORE SETUP FOR PACKET MANAGEMENT MOV #C1.CON!C1.SYN,(R3) ; ENTER C1.SYN,C1.CON STATE. JMPV PORT,PORSYN ; START SYNCHRONIZATION 50$: PUSH ; SAVE REGISTERS CALL @SAVSTK ; TELL CON ABOUT ERROR POP ; RESTORE OUR REGISTERS SEC ; ENSURE CARRY SET 60$: RETURN .PAGE .SBTTL XXOUT - TIME OUT ENTRY POINT ;+ ; **-XXOUT-TIME OUT ENTRY POINT ; ; REASONS FOR TIMEOUTS ARE: ; ; 1. THE TIMER ON THE OLDEST COMMAND IN THE CONTROLLER HAS EXPIRED. ; 2. (DISK ONLY) A CONTROLLER RE-SYNCH IS DONE AND OP.ONL'S MUST BE ; RE-ISSUED FOR ANY UNITS STILL MARKED AS SPINNING UP (US.SPU=1). ; THE TIMEOUT IS SET AND PROCESSED BY THE RECSIO ROUTINE. ; 3. A FATAL ERROR HAS BEEN DETECTED AND NOW A RE-SYNCH MUST COMMENCE. ; CLAERR IS CALLED WHENEVER A FATAL ERROR IS DETECTED AND SETS A ; 1 SECOND TIMER. ; 4. CONTROLLER SYNCHRONIZATION STEP HAS TIMED OUT WHICH IS FATAL ERROR. ; ; INPUTS: ; ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ;- DUOUT: MUOUT: MOV S.PBIA(R4),@KISR6 ; MAP PORT DRIVER (IN APR 6) MOV S.PBIA(R4),@#KINAR6 ; FOR I/D SYSTEMS MAP BOTH MOV S.QST(R4),R2 ; GET QST MOV (R2),R3 ; GET CST BIT #C1.RDY,(R3) ; READY STATE? BEQ 20$ ; NO. CONTINUE, ELSE THIS ; MUST BE A CMD TMO. FOR TAPE .IF DF D$$DSK BIT #C1.R2,(R3) ; RECOVERY IN PROGRESS? BEQ 10$ ; NO. THIS MUST BE A COMMAND TST C.OLHD(R3) ; COMMANDS IN PROGRESS? BNE 10$ ; YES. MUST BE COMMAND TIMEOUT ; ; WE MUST BE HERE IN ORDER TO RETRY UNIT ONLINES AFTER A FATAL ; ERROR RE-SYNCHRONIZATION. FOR EACH UNIT THAT USED TO BE ONLINE ; (US.SPU=1), RETRYS, IN CASE OF FAILURE, ARE DONE EVERY FEW SECONDS ; BIS #C1.R1,(R3) ; NOTE THAT WE NEED TO DO ONLINES JMP RECSIO ; GO DO THEM .ENDC ;D$$DSK ; ; WE ARE HERE BECAUSE A COMMAND JUST TIMED OUT ; 10$: BIT #C1.TMO!C1.GCS,(R3) ; DID GCS COMMAND TIME OUT? BEQ 15$ ; NO. CONTINUE JMP TMOERR ; YES. GO START RESYNCH 15$: BIS #C1.GCS,(R3) ; INDICATE NEED TO DO OP.GCS MOVB S.ITM(R4),S.CTM(R4) ; RESET TMO. COUNT CALLV PORT,PKTCH1 ; HAVE THE RESOURCES TO DO IT NOW? BCS 17$ ; NO. RETURN JMP GCSSIO ; GO ISSUE IT 17$: RETURN ; ; IF WE GET HERE EITHER WE TIMED OUT BEFORE THE CONTROLLER GOT UP ; OR WE ARE HERE TO START A RE-SYNCHRONIZATION ; 20$: BIT #C1.FAT,(R3) ; FATAL STATE? BEQ 30$ ; NO. CONTINUE BIC #C1.FAT,(R3) ; YES. CLEAR FATAL STATE JMPV PORT,PORSYN ; AND START RESYNCH WITH THE CONT 30$: SEC ; LOG CONTROLLER ERROR JMP CLAERR ; JUMP TO ERROR ROUTINE .PAGE .SBTTL XXPWF - POWERFAIL ENTRY POINT ;+ ; **-DUPWF- DISK POWERFAIL ENTRY POINT ; **-MUPWF- TAPE POWERFAIL ENTRY POINT ; ; THIS ROUTINE HANDLES POWERFAIL RECOVERY FOR CONTROLLERS. CLAERR WILL ; DEAL WITH ALL THE UNITS. ; ; INPUTS: ; ; C = 1 INDICATES CONTROLLER POWERFAIL ; R2 = KRB ADDRESS ; R3 = CTB ADDRESS ; ; C = 0 INDICATES UNIT POWERFAIL ; R3 = CONTROLLER INDEX ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; CONTROLLER ONLINE ;- DUPWF: MUPWF: BCC 20$ ; RETURN FOR UNIT; CLAERR WILL DO IT MOV L.DCB(R3),R3 ; GET DCB MOV D.UCB(R3),R5 ; NOW UCB MOV U.SCB(R5),R4 ; NOW SCB CALL MAPD ; MAP PORT DRIVER (IN APR 6) MOV S.QST(R4),R2 ; GET QST MOV (R2),R3 ; GET CST MOVB #RETRY,Q.RTY(R2) ; SET RETRY COUNT JMP CLAERR ; RESET STATES, QUEUES, AND SET UP TMO ; COUNT. THE TIMEOUT ROUTINE WILL START ; RE-SYNCH FOR DISK. 20$: RETURN .PAGE .SBTTL XXUCB - CON UNIT ONLINE ENTRY POINT ;+ ; **-XXUCB - CON UNIT ONLINE ENTRY POINT ; ; ROUTINE DESCRIPTION ; ; INPUTS: ; ; R3 = CONTROLLER INDEX (S.KRB .NE. 0) ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; 0(SP) - RETURN ADDRESS ; 2(SP) - DELAYED RETURN ADDRESS ; C SET OFFLINE ; C CLEAR ONLINE ; $CSERR SET TO 1, SUCCESS ; $SCOFL > 0 THEN ONLINE FOR SYSTEM DEVICE ; ; OUTPUTS: ; ; R4-R5 ARE PRESERVED ; ; $SCERR = 0 OPERATION IS PENDING (MAXIMUM TIME IS 60 SECONDS) ; $SCERR < 0 OPERATION IS A FAILURE $SCERR CONTAINS CODE ; $SCERR = 1 OPERATION IS A SUCCESS ; 0(SP) = RETURN ADDRESS OF CALLER OF $UCBSC ROUTINE ;- MUUCB: DUUCB:: .IF DF D$$DSK BCS 40$ ; IF CS OFFLINE REQUEST TST U.BPKT+2(R5) ; REPLACEMENT QUEUE ALREADY INITIALIZED? BNE 10$ ; YES MOV #U.BPKT,U.BPKT+2(R5) ; NO. SET UP FOR ZERO ENTRY QUEUE ADD R5,U.BPKT+2(R5) ; SHOW IT AS EMPTY 10$: MOV S.KRB(R4),R2 ; GET KRB MOV R5,K.OWN(R2) ; MARK UNIT AS OWNING CONTROLLER MOV U.UC2X(R5),R0 ; EXTENSION ALREADY THERE? BNE 30$ ; YES. DON'T GET ANOTHER ONE .IF DF,D$$PRT ;DC412 BIT #UU.PRT,U.UTIL(R5) ; ARE WE ALREADY A SUB-UNIT? ;DC412 BEQ 15$ ; NOPE, DON'T DUPLICATE ;DC412 MOV U.KRB1(R5),R0 ; GET THE SUBCONTROLLER ;DC412 BEQ 15$ ; KRB1 NOT SET UP YET ;DC412 MOV K1.OWN(R0),R0 ; GET THE OWNER UNIT ;DC412 CMP R5,R0 ; IS THAT US? ;DC412 BEQ 15$ ; GO AHEAD, NOT ALL READY YET ;DC412 MOV U.UC2X(R0),R0 ; GET THEIR EXTENSION ;DC412 BEQ 19$ ; IF EQ, WE CAN'T DO THIS ;DC412 MOV R0,@KISR6 ; MAP TO THE UCB2X ;DC412 INCB @#140000+X.PONL ; SHOW ANOTHER UNIT ONLINE ;DC412 BR 30$ ; AND CONTINUE ;DC412 15$: MOV #</64.>,R1 ; SIZE W/ PARTITION INFO ;DC412 .IFF ;DF,D$$PRT ;DC412 MOV #</64.>,R1 ; SIZE W/O PARTITION INFO ;DC412 .ENDC ;DF,D$$PRT ;DC412 CALL @ALSEC ; ALLOCATE A CHUNK OF SECONDARY POOL ;DC412 BCC 30$ ; OK ;DC412 19$: MOVB #IE.UPN,@SCERR ; SET FAILURE CODE ;DC412 20$: RETURN ;**-5 30$: MOV R0,U.UC2X(R5) ; SAVE BLOCK ADDRESS .IF DF D$$PRT ;DC412 BIT #UU.PRT,U.UTIL(R5) ; ARE WE A PARTITIONED UNIT ;DC412 BEQ 35$ ; IF EQ, NOPE, CONTINUE ;DC412 ;DC412 MOV U.KRB1(R5),R0 ; GET THE SUB KRB ;DC412 BEQ 35$ ; NOT INITIALIZED, WAIT FOR RCT ;DC412 TST K1.OWN(R0) ; DO WE HAVE AN OWNER YET? ;DC412 BNE 35$ ; YUP, NO NEED TO UPDATE ;DC412 ;DC412 MOV R5,K1.OWN(R0) ; SHOW US AS OWNER OF SUB-KRB ;DC412 35$: .ENDC ;DF,D$$PRT ;DC412 TSTB @SCOFL ; SPECIAL OFFLINE TO ONLINE TRANSITION? BLE 20$ ; NO CALL MAPD ; MAP SECOND 4K WORDS ++++ HUH? MOV S.QST(R4),R2 ; GET QST MOV (R2),R3 ; GET CST CLRB @SCERR ; STATUS CHANGE IN PROGRESS BIS #UU.SPC,U.UTIL(R5) ; SPECIAL ONLINE JMP ONLSIO ; BRING UNIT ONLINE 40$: CALL MAPD ; MAP PORT DRIVER (IN APR 6) MOV S.QST(R4),R2 ; GET QST MOV (R2),R3 ; GET CST MOV C.OLHD(R3),R1 ; GET QUEUE HEAD CALL 60$ ; CHECK THIS QUEUE MOV U.BPKT(R5),R1 ; CHECK BAD PACKET QUEUE CALL 60$ ; IF ANY BIC #UU.SIO,U.UTIL(R5) ; CLEAR STALL I/O TO THIS DEVICE MOV U.UC2X(R5),R0 ; GET ADDRESS OF BLOCK BEQ 90$ ; IF EQ, DON'T DO ANYTHING ;DC412 CLR U.UC2X(R5) ; SHOW THE UCBX AS DELETED ;DC412 .IF DF,D$$PRT ;DC412 BIT #UU.PRT,U.UTIL(R5) ; ARE WE A PARTITION? ;DC412 BEQ 50$ ; NOPE, JUST DELETE UCBX ;DC412 ;DC412 MOV U.KRB1(R5),R1 ; GET THE KRB1 ADDRESS ;DC412 BEQ 50$ ; NOT PRESENT, JUST DO IT ;DC412 ;DC412 MOV R0,@KISR6 ; MAP TO THE UCBX ;DC412 DECB @#140000+X.PONL ; DROP COUNT OF UNITS INVOLVED ;DC412 BEQ 50$ ; IF EQ, WE DON'T HAVE TO FIND THE MASTE;DC412 ;DC412 CMP K1.OWN(R1),R5 ; ARE WE THE MASTER? ;DC412 BNE 50$ ; NOPE, JUST CLEAN UP ... ;DC412 ;DC412 MOV R1,R2 ; COPY THE KRB1 ADDRESS ;DC412 ADD #K1.UCB,R2 ; POINT TO THE UCB TABLE ;DC412 45$: MOV (R2)+,R3 ; GET NEXT UCB ;DC412 CMP R3,R5 ; IS THAT US? ;DC412 BEQ 45$ ; YES, CONTINUE ;DC412 TST U.UC2X(R3) ; UCBX PRESENT? ;DC412 BEQ 45$ ; NOPE, CAN'T SET THEM UP ;DC412 MOV R3,K1.OWN(R1) ; WE HAVE A NEW MASTER ;DC412 BR 90$ ; AND WE ARE DONE ;DC412 ;DC412 50$: MOV #</64.>,R1 ; SIZE W/ PARTITION INFO ;DC412 .IFF ;DF,D$$PRT ;DC412 MOV #</64.>,R1 ; SIZE W/O PARTITION INFO ;DC412 .ENDC ;DF,D$$PRT ;DC412 CALLR @DESEC ; DEALLOCATE A CHUNK OF SECONDARY POOL ;**-2 60$: BEQ 90$ ; EMPTY QUEUE, MUST BE AFTER LOAD OF ; R1 WITH FIRST (P)IOP ON QUEUE 70$: CMP R5,I.UCB(R1) ; FOR THIS UNIT? BNE 80$ ; NO. CHECK NEXT TST (SP)+ ; CLEAR RETURN ADDRESS MOVB #IE.VER,@SCERR ; SET FAILURE CODE RETURN 80$: MOV (R1),R1 ; GET NEXT IOP BNE 70$ ; CHECK IT 90$: .ENDC ;D$$DSK RETURN .PAGE .IF DF,T$$APE .SBTTL ABOSIO - KILL I/O'S ON UNIT REQUIRING IT ;+ ; **-ABOSIO-KILL I/O'S ON UNITS REQUIRING IT ; ; THIS ROUTINE SCANS THROUGH THE C.OLHD QUEUE FOR THE CURRENT CONTROLLER AND ; LOCATES ANY IOPS THAT HAVE THE IP.ABO BIT SET (BY XXCAN). IF THE IP.PND ; BIT IS CLEAR, AN ABORT COMMAND IS ISSUED. CHECKING IS DONE IN REVERSE ; ORDER TO PREVENT THE N-TH I/O FROM ACTUALLY STARTING AFTER ABORTING THE ; N-TH MINUS 1 I/O. ; ; INPUT: ; ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; ; OUTPUT: ; ;- ABOSIO: 10$: CLR LSTPKT ; NO PACKET FOUND MOV S.QST(R4),R2 ; GET QST MOV (R2),R0 ; GET CST ADD #C.OLHD,R0 ; POINT TO LIST HEAD TO PROCESS 20$: MOV (R0),R0 ; GET NEXT IOP BEQ 30$ ; ALL DONE CMP #IO.KIL,I.FCN(R0) ; 'KILL' COMMAND? BEQ 20$ ; YES. LOOK AT ANOTHER BITB #IP.ABO,I.FLAG(R0) ; SHOULD THIS CMD BE ABORTED? ;DC412 BEQ 20$ ; NO. FIND ANOTHER ONE ;DC412 BITB #IP.PND,I.FLAG(R0) ; ABO ALREADY ISSUED FOR THIS? ;DC412 BNE 20$ ; YES. ;**-3 MOV R0,LSTPKT ; SAVE LAST PACKET BR 20$ ; CHECK FOR MORE 30$: TST LSTPKT ; ANYTHING FOUND? BEQ 40$ ; NO. CALLV PORT,PKTCHK ; ANY RESOURCES AVAILABLE? BCS 70$ ; NO. TRY AGAIN LATER MOV LSTPKT,R0 ; GET IOP MOV I.UCB(R0),R5 ; GET UCB MOV U.SCB(R5),R4 ; GET SCB CALL PIOPAL ; ALLOCATE PIOP FOR 'DUMMY' COMMAND BCS 70$ ; UNABLE TO MOV #IO.KIL,I.FCN(R3) ; MAKE SURE WE KNOW WHENCE IT CAME MOV #ABOFUN,R0 ; ABORT COMMAND CALL CMDCOM ; BUILD TEMPLATE MOV LSTPKT,R0 ; GET IOP ADDR MOVB I.FLAG(R0),P.OTRF(R1) ; GET COMMAND REFERENCE NUMBER 1 ;DC412 BIC #177760,P.OTRF(R1) ; USE ONLY 4 BITS WORTH (ACTUAL #) ;DC412 MOV R0,P.OTRF+2(R1) ; PUT IN ASSOCIATED IOP ADDR ;DC412 BISB #IP.PND,I.FLAG(R0) ; SHOW ABORT COMMAND ISSUED ;DC412 PUSH <#10$> ; GO BACK TO SCANNING LIST ;**-4 CALL CMDSEN ; GO ISSUE THE COMMAND ; ; END PACKET PROCESSING ; CLR R0 ; INDICATE NO I/O TO COMPLETE PUSH <#0> ; NO INFORMATION NEEDED CALL ENDCMO ; CLEAN UP AND RETURN HERE BR 10$ ; MAKE ANOTHER PASS THROUGH LIST 40$: PUSH <#SCUCB> ; SCAN UCB LIST 50$: CALL @(SP)+ ; CALL SCUCB AS A COROUTINE BCS 60$ ; ALL DONE BIT #UU.ABO,U.UTIL(R5) ; DID XXCAN SET SERIAL MODE? BEQ 50$ ; NO. BIC #UU.SER!UU.ABO,U.UTIL(R5) ; YES. RESET SERIAL AND ABORT MODE BR 50$ ; FIND ANOTHER UNIT 60$: CALL 70$ ; RESTORE QST/CST ADRESSES BIC #C1.ABO,(R3) ; LEAVE ABORT STATE BR 80$ ; RETURN 70$: MOV S.QST(R4),R2 ; GET QST MOV (R2),R3 ; GET CST 80$: RETURN .ENDC ;T$$APE .PAGE .SBTTL CLAATN - CLASS ATTENTION MESSAGE PROCESSING ;+ ; **-CLAATN - CLASS ATTENTION MESSAGE PROCESSING ; ; ATTENTION MESSAGES WILL CAUSE TRANSITION TO UU.ATN STATE. ; ; INPUTS: ; ; R1 = END PACKET ADDRESS ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ;- CLAATN: MOV R1,R2 ; SAVE COPY CMPB #OP.AVA,P.OPCD(R1) ; AVAILABLE ATTENTION MESSAGE? BNE 40$ ; NO. DEALLOCATE PACKET PUSH <#SCUCB> ; SCAN UCB ROUTINE 10$: CALL @(SP)+ ; CALL COROUTINE BCS 40$ ; NO MORE UCBS CMPB P.UNIT(R2),U.UNIT(R5) ; ATTENTION MESSAGE FOR THIS UCB? BNE 10$ ; NO .IF DF,D$$DSK BIT #UU.IOS,U.UTIL(R5) ; I/O STALLED TO THIS UNIT? BNE 20$ ; YES. MARK THIS UNIT BITB #US.MNT,U.STS(R5) ; WAS UNIT MOUNTED? BNE 30$ ; NO. SKIP THIS ONE BIT #UU.SIO,U.UTIL(R5) ; CAN THIS UNIT STALL I/O? BEQ 30$ ; NO. CONTINUE 20$: .ENDC ;D$$DSK BIT #UU.ATN,U.UTIL(R5) ; DID WE ALREADY? BNE 30$ ; YES. DON'T DO IT AGAIN BIS #C1.GUS,(R3) ; SET GUS STATE BIS #UU.GUS!UU.SER!UU.ATN,U.UTIL(R5); SET GUS, SERIAL AND ATN 30$: ADD #10,SP ; FLUSH UCB SCAN 40$: MOV R2,R1 ; GET END PACKET MOV S.QST(R4),R2 ; GET QST CALLV PORT,PKTDR ; DEALLOCATE PACKET RETURN .PAGE .SBTTL CLACMD - INITIATOR AND CONTINUATION ENTRY POINT ;+ ; **-CLACMD-INITIATOR ENTRY POINT AND CONTINUATION ENTRY POINT ; ; DECIDE WHAT TO DO NEXT BASED ON CONNECTION MODES. A MODE IS A COMBINATION ; OF STATES. ; ; INPUTS: ; ; R2 = QST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2 = PRESERVED ; R4-R5 = PRESERVED ; R3 = CST ADDRESS ;- CLACMD: MOV (R2),R3 ; GET CST BIT #C1.RDY,(R3) ; RDY SET? BEQ 70$ ; NO. 10$: BIT #^C,(R3) ; ANYTHING BUT RDY OR DQU SET? BNE 20$ ; YES. SPECIAL STATE EXISTS TST (R4) ; ANY I/O TO START? BEQ 70$ ; NO. JUST EXIT .IF DF D$$DSK BITB #C2.SHD,C.FLAG(R3) ; IS THIS A RECURSIVE ENTRY? C2.SHD IS ; ONLY FOR TESTING RECUSRSION THAT MIGHT ; OCCUR DURING SHADOWING BNE 90$ ; YES. JUST EXIT ;DC412 ;**-1 .IF DF DU$CHK ; IF QUEUE OPTIMIZATION BITB #S3.OPT,S.ST3(R4) ; QUEUE OPTIMIZATION ENABLED? BEQ 13$ ; NO. GO CHECK RESOURCES MOV C.OLHD(R3),R1 ; GET OUTSTANDING REQUEST BEQ 15$ ; IF NONE, WE CAN ISSUE A REQUEST TST (R1) ; MORE THAN ONE OUTSTANDING? BEQ 15$ ; NO. ISSUE THIS ONE BR 70$ ; CAN'T ISSUE ONE NOW .ENDC ; DU$CHK .IFTF ;D$$DSK 13$: CALLV PORT,PKTCHK ; RESOURCES AVAILABLE? BCS 70$ ; NO. RETURN 15$: CALLR CMDSIO ; START AN I/O 20$: .IF DF M$$PRO MOV @CPURM,-(SP) ; DETERMINE IF WE NEED TO FORK? BIT S.URM(R4),@(SP)+ ; ARE WE ON THE RIGHT CPU? BNE 25$ ; IF NE, YES, CONTINUE BITB #C2.FRK,C.FLAG(R3) ; DO WE HAVE A BLOCK QUEUED? BNE 90$ ; YES, JUST RETURN ;DC412 ;**-1 BISB #C2.FRK,C.FLAG(R3) ; FLAG THAT WE ARE IN THE FORK QUEUE MOV S.URM(R4),R2 ; GET THE DESIRED URM .IF DF T$$APE MOV #MUINI,R3 ; SET TAPE INITIATOR ENTRY POINT .IFF ;DF,T$$APE MOV #DUINI,R3 ; SET DISK INITIATOR ENTRY POINT .ENDC ;DF T$$APE CALLR @EXROP ; FORK TO THE RIGHT CPU 25$: BICB #C2.FRK,C.FLAG(R3) ; RESET OUR IN-PROGRESS FORK BIT .ENDC ;DF M$$PRO CALLV PORT,PKTCHK ; RESOURCES AVAILABLE? BCS 70$ ; NO. RETURN BIT #C1.GCS,(R3) ; GET COMMAND STATUS STATE? BEQ 30$ ; NO. KEEP LOOKING CALLR GCSSIO ; ISSUE GCS COMMAND 30$: BIT #C1.GUS,(R3) ; GET UNIT STATUS STATE BEQ 50$ ; NO. CONTINUE CALLR GUSSIO ; ISSUE GUS COMMANDS 50$: .IFT ;D$$DSK BIT #C1.REC,(R3) ; RESYNCH RECOVERY? BEQ 70$ ; NO. KEEP LOOKING CALLR RECSIO ; GO TO RECOVERY ROUTINE .IFF ;D$$DSK BIT #C1.ABO,(R3) ; ABORT STATE? BEQ 70$ ; NO. KEEP LOOKING CALLR ABOSIO ; ISSUE ABORT COMMANDS .ENDC ;D$$DSK 70$: ;DC412 BIT #C1.DQU,(R3) ; SHOULD WE DEQUEUE UMRS? ;DC412 BEQ 90$ ; NO ;DC412 BIC #C1.DQU,(R3) ; RESET DEQUEUE STATE ;DC412 CALL @DQUMR ; CALL IT AS A COROUTINE ;DC412 90$: RETURN ; DON'T KNOW WHAT TO DO, SO RETURN ;DC412 .PAGE ;**-5 .SBTTL CLADAT - HANDLE DATAGRAMS ;+ ; **-CLADAT - PROCESS DATAGRAMS ; ; INPUTS: ; ; R1 = END PACKET ADDRESS ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ;- CLADAT: .IF DF E$$LOG MOV R1,KEEPR1 ; SAVE END PACKET PUSH <#SCUCB> ; PUSH "SCAN UCB'S" ROUTINE ON STACK 10$: CALL @(SP)+ ; CALL THE CO-ROUTINE BCS 20$ ; NO MORE UCBS MOV KEEPR1,R1 ; GET END PACKET CMPB P.UNIT(R1),U.UNIT(R5) ; PACKET FOR THIS UCB? BNE 10$ ; NO ADD #10,SP ; YES. FLUSH THE STACK .IF DF,D$$DSK BIT #UU.SEL,U.UTIL(R5) ; SHOULD PACKET BE LOGGED FOR THIS UNIT? BNE 20$ ; NO .ENDC ;D$$DSK MOV P.STS(R1),R0 ; GET STATUS CODE BIC #^C,R0 ; GET MAJOR STATUS PORTION MOVB RSXTAB(R0),R0 ; MAP IT TO AN RSX STATUS CODE BIC #177400,R0 ; MAKE SURE IT IS A BYTE STATUS CALL LERR ; LOG THE PACKET 20$: MOV KEEPR1,R1 ; GET END PACKET .ENDC JMPV PORT,PKTDR ; DEALLOCATE RECEIVE PACKET .PAGE .SBTTL CLAEND - CLASS DISPATCHER FOR END PACKETS ;+ ; **-CLAEND-CLASS DISPATCHER FOR END PACKETS ; ; ROUTINE DESCRIPTION ; ; WHEN THE PORT DRIVER RECEIVES END PACKETS IT WILL CALL THE CLASS DRIVER AT ; CLAEND FOR EACH END PACKET. THIS PICKS UP THE THREAD FOR EACH I/O AND RETURNS ; TO THE CORRECT PLACE TO PROCESS THE END PACKET AND COMPLETE THE I/O. ; ; INPUTS: ; ; R0 = ; R1 = END PACKET ADDRESS ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2-R5 ARE PRESERVED ;- CLAEND: BITB #OP.AVA,P.OPCD(R1) ; ATTENTION MESSAGE? BNE 100$ ; YES 10$: MOV P.CRF+2(R1),R5 ; GET IOP MOV I.UCB(R5),R5 ; GET UCB CMPB #OP.GCS!OP.END,P.OPCD(R1) ; GET CMD STATUS? BEQ 200$ ; YES 20$: MOV C.OLHD(R3),R0 ; GET ENTRY IN QUEUE BEQ 45$ ; NONE MOV P.CRF+2(R1),R3 ; IOP ADDRESS 30$: CMP R3,R0 ; SAME? BEQ 50$ ; YES MOV (R0),R0 ; NO. GET NEXT ENTRY BNE 30$ ; CHECK IT 40$: MOV (R2),R3 ; GET CST 45$: JMPV PORT,PKTDR ; DEALLOCATE PACKET 50$: .IF DF D$$DSK TST P.STS(R1) ; SUCCESS? BEQ 70$ ; YES CALL ENDSIO ; GO SEE IF WE SHOULD STALL I/O BCC 70$ ; CC = I/O WAS NOT STALLED RETURN ; CS = I/O WAS STALLED 70$: .ENDC ; DISK CONDITIONAL JMP @I.PRM+6(R3) ; GO TO END PROCESS ROUTINE 100$: CALLR CLAATN ; PROCESS ATTENTION MESSAGE 200$: CALLR TMOGCS ; PROCESS IN TMOGCS ROUTINE .PAGE .SBTTL CLAERR - FATAL ERROR RECOVERY ;+ ; **-CLAERR- A FATAL ERROR HAS OCCURRED ; ; ON FATAL ERROR RESET CONTROLLER AND UNIT STATES. CLEAN UP C.OLHD QUEUE ; DEALLOCATING ALL PIOPS ; ; FOR DISK, MOVE C.OLHD OLDEST I/O TO C.REDO SO THAT IT WILL BE RETRIED ; THE CONTROLLER COMES BACK. MOVE ALL COMMANDS IN C.OLHD TO THE FRONT O ; ; FOR TAPE, MOVE ALL COMMANDS ; ; INPUTS: ; ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2,R3,R4 PRESERVED ; R5 IS A UCB ADDRESS ;- TMOERR: MOVB #4,Q.RTY(R2) ; SET UP THE RETRY COUNT SEC ; LOG ERROR CLAERR: BIT #C1.FAT,(R3) ; DID WE ALREADY DO ALL THIS? BEQ 10$ ; NO. IT'S TIME TO DO IT NOW RETURN ; DON'T DO IT AGAIN 10$: ; ; IF CARRY IS SET THEN LOG FATAL HARDWARE ERROR ; THIS ROUTINE IS CALLED ON 11M BOOT IN WHICH CASE THERE IS NO ERROR ; .IF DF E$$LOG BCC 20$ MOV #IE.FHE&377,R0 ; INDICATE FATAL HARDWARE ERROR CALL CERR ; LOG CONTROLLER ERROR .ENDC 20$: CALLV PORT,STOMP ; STOMP THE CONTROLLER ; ; RESET ALL STATES EXCEPT C1.REC,C1.R2,C1.UMR,C1.CON ; BIC #^C,(R3) BIS #C1.FAT,(R3) ; MARK THAT WE DID THIS MOV R3,R0 ; GET CST ADD #C.OLHD,R0 ; POINT TO THE C.OLHD QUEUE ; ; DEALLOCATE ALL PIOPS FROM C.OLHD ; MOV R0,R1 ; COPY THE QUEUE HEAD MOV (R1),R1 ; GET NEXT PACKET BEQ 50$ ; NONE LEFT 30$: PUSH <(R1)> ; POINTER TO NEXT IOP BITB #IP.FAK,I.FLAG(R1) ; IS IT A PIOP? ;DC412 BEQ 40$ ; NO. CONTINUE ;**-1 PUSH ; SAVE R0 AND R3 CALL @QRMVA ; REMOVE IT FROM THE QUEUE POP ; RESTORE R3 CALL PIOPDE ; DEALLOCATE IT POP ; RESTORE R0 40$: POP ; RESTORE R1 BNE 30$ ; GET ANOTHER 50$: MOV S.QST(R4),R2 ; RESTORE THE MOV (R2),R3 ; RESTORE CST ADDRESS TO R3 ; ; TAKE ANY IOP'S WAITING FOR UMR'S OUT OF THE UMR WAIT QUEUE PUT THEM BACK IN ; S.LHD. CHANGE THE PRIORITY TO INSURE THAT IT GOES AT THE BEGINNING OF THE ; QUEUE, AND CLEAR THE C1.UMR BIT ; BIT #C1.UMR,(R3) ; WAS THIS CONTROLLER WAITING FOR UMRS? BEQ 80$ ; IF EQ NO PUSH ; SAVE R2 AND R3 MOV @UMRWT,R0 ; GET HEAD OF THE UMR WAIT QUEUE BEQ 70$ ; IF NOTHING, SKIP THIS SECTION MOV R0,R1 ; COPY THE QUEUE HEAD TO R1 60$: MOV (R1),R1 ; GET A WAIT BLOCK BEQ 70$ ; NONE LEFT CMP 10(R1),R4 ; WAIT BLOCK FOR THIS CONTROLLER? ; ..(SAME SCB) BNE 60$ ; NO. TRY ANOTHER CALL @QRMVA ; REMOVE THE BLOCK FROM THE QUEUE MOV 6(R1),R1 ; GET IOP ADDRESS FROM THE WAIT BLOCK .IF DF D$$DSK&DU$CHK ; IF QUEUE OPTIMIZATION MOV I.UCB(R1),R5 ; MAKE SURE WE HAVE THE RIGHT UCB CALL REQUE ; RECONVERT THE LBN .ENDC ;D$$DSK&DU$CHK MOV R4,R0 ; PUT THE S.LHD QUEUE ON R0 CALL @QINSB ; INSERT AT THE BEGINNING OF THE QUEUE 70$: POP ; RESTORE R3 AND R2 BIC #C1.UMR,(R3) ; CLEAR THE UMR BIT ; ; DEALLOCATE ANY UMR'S USED ; 80$: ADD #C.OLHD,R3 ; POINT TO THE .OLHD QUEUE 90$: MOV (R3),R3 ; GET A PACKET BEQ 100$ ; NONE LEFT BITB #IP.UMR,I.FLAG(R3) ; IS IT USING UMRS? ;DC412 BEQ 90$ ; NO. CONTINUE ;**-1 CLR R0 ; TELL ENDCM1 NOT TO FINISH THE I/O PUSH ; SAVE R3 CALL ENDCM1 ; GO DEALLOCATE THE UMRS POP ; RESTORE R3 BR 90$ ; GO TRY ANOTHER 100$: MOV (R2),R3 ; RESTORE THE CST DECB Q.RTY(R2) ; DECREMENT THE RETRY COUNT BGT 110$ ; IF GT, WE STILL HAVE MORE TRIES ; ; WE'VE EXHAUSTED OUR TIMEOUTS. CLEAN OUT THE QUEUES AND EXIT. ; MOV (R2),R1 ; GET CST CLR (R1) ; SET THE STATE OFFLINE ADD #C.OLHD,R1 ; POINTER TO THE C.OLHD QUEUE CALL FINIO ; FLUSH THE QUEUE MOV R4,R1 ; GET SCB ADDDRESS ADD #S.LHD,R1 ; POINTER TO THE S.LHD QUEUE JMP FINIO ; FLUSH THAT QUEUE TUEUE, AND EXIT 110$: MOVB #1,S.CTM(R4) ; SET A 1 SECOND TIMEOUT COUNT ; RESYNCH WILL START FROM TIMEOUT. TST S.BSYU(R4) ; IS THERE A BUSY UNIT BNE 120$ ; IF NE, YES MOV R5,S.BSYU(R4) ; ELSE MAKE ONE BUSY BISB #US.BSY,U.STS(R5) 120$: ADD #C.OLHD,R3 ; POINTER TO THE C.OLHD QUEUE MOV R3,R0 ; SET UP QUEUE ADDRESS .IF DF D$$DSK ; ; SEE IF WE'VE RETRYED THE OLDEST COMMAND ; TST C.REDO-C.OLHD(R3) ; IS THE OLDEST CMD STILL HERE? BEQ 130$ ; IF EQ, NO. SKIP THIS SECTION ; ; ; IF WE HAVE ALREADY TRYED THE OLDEST COMMAND TWICE ; IT MUST BE 'FUNNY' SO COMPLETE IT AS IE.ABO. ; CMP (R3),C.REDO-C.OLHD(R3) ; OLDEST AT LAST FAIL THE SAME ; AS OLDEST THIS TIME? BNE 130$ ; IF NE, CONTINUE ; ELSE THE OLDEST HAS FAILED TWICE ; SO COMPLETE IT AS IE.ABO MOV R3,R0 ; R0 IS THE QUEUE MOV (R0),R1 ; R1 IS THE OLDEST IOP CALL @QRMVA ; REMOVE THE OLDEST CMD FROM THE QUEUE ; R1 IS STILL IOP ADDRESS MOV S.QST(R4),R2 ; R2,R3 DESTROYED BY $QRMVA ; FOR ENDCOM: MOV I.UCB(R1),R5 ; R5 = THE UCB ADDRESS ; R4 = THE SCB ADDRESS MOV R1,R3 ; R3 = IOP ADDRESS CLR R1 ; R1 = BYTE COUNT MOV #IE.ABO&377,R0 ; R0 = #IE.ABO CALL ENDCM1 ; FINISH THE IOP ; ; ADD C.OLHD QUEUE TO C.REQU AND REMEMBER OLDEST FAILED COMMAND ; 130$: MOV (R2),R3 ; GET CST BACK MOV C.OLHD(R3),C.REDO(R3) ; REMEMBER OLDEST FAILED CMD MOV R3,R0 ; PUT THE CST IN R0 ADD #C.OLHD,R0 ; R0 POINTS TO C.OLHD QUEUE TST (R0) ; IS THERE ANYTHING IN THE QUEUE? BEQ 150$ ; NO. JUST CONTINUE MOV (R2),R1 ; ADD #C.REQU,R1 ; R1 IS THE ADDRESS OF THE C.REQU PUSH <(R1)> ; SAVE THE ADDRESS OF THE FIRST P BNE 140$ ; WAS THERE ANYTHING IN THE QUEUE MOV 2(R0),2(R1) ; NO. COPY THE LAST PACKET POINTE 140$: MOV (R0),(R1) ; COPY THE POINTER FROM C.OLHD CLR (R0) ; QUEUE IS NOW EMPTY PUSH <2(R0)> ; SAVE THE LAST PACKET IN THE C.O MOV R0,2(R0) ; FINISH SETTING UP THE EMPTY QUE POP ; GET BACK THE ADDRESS OF THE LAS POP <(R0)> ; FIRST IN QUEUE NOW ON END 150$: BIS #C1.REC!C1.R1!C1.R2,(R3); INDICATE WE ARE IN RECOVERY .IFF ;D$$DSK MOV R0,R1 ; MOVE THE C.OLHD POINTER TO R1 F CALL FINIO ; FINISH ALL I/O IN C.OLHD AS IE. .IFTF ;D$$DSK PUSH <#SCUCB> ; PUSH ADDRESS OF COROUTINE TO SCAN UCBS 160$: CALL @(SP)+ ; GET A UCB BCS 190$ ; NONE LEFT .IFT ;D$$DSK BIT #UU.RDY,U.UTIL(R5) ; WAS THE UNIT IN THE READY STATE? BEQ 180$ ; NO. KEEP LOOKING BITB #US.OFL,U.ST2(R5) ; IS THE UNIT ONLINE? BNE 180$ ; NO. THEN DON'T BRING IT UP BISB #US.SPU,U.STS(R5) ; SET SPIN UP BIT 170$: .ENDC ;D$$DSK .IIF DF T$$APE BISB #US.PWF,U.STS(R5) ; SET THE POWERFAIL BIT 180$: BIC #^C,U.UTIL(R5); CLEAR ; UTILITY WORD. KEEP SOME BITS THE SAME ; (CONTEXT ACROSS COMMANDS) CLR U.CNT(R5) ; U.CNT USED FOR RETRY COUNT BR 160$ ; GO GET ANOTHER ONE 190$: RETURN .PAGE .SBTTL CLASUP - CLASS SET UP ROUTINE ;+ ;- CLASUP - CLASS SET UP ROUTINE ; ; THIS ROUTINE WILL MAKE SURE THAT THE COMMON IS IN MEMORY AND ; PROPERLY SET UP. THE FOLLOWING FUNCTIONS ARE PERFORMED: ; ; 1. DETERMINE WHICH PORT THE CONTROLLER IS USING ; 2. MAKE SURE THE PORT IS IN MEMORY. ; 3. IF PORT IS NOT PRESENT, TRY TO LOAD IT. IF THAT FAILS, THE ; DRIVER MUST BE DISABLED AND SEND MESSAGE VIA TKTN. ; 4. IF PORT IS PRESENT, FILL IN S.PBIA IN SCB. ; 5. THE PORT MUST BE ; - FIXED ; - NON SHUFFLABLE ; - NON REMOVABLE (BUMP P.RMCT) ; - NOT TOUCHABLE ; ; INPUTS ; ; R4 = SCB ADDRESS ; R1 = VIRTUAL CIRCUIT ID ; ; OUTPUTS ; ; ALL REG ARE PRESERVED ; C=0 SUCCESS, COMMON LOADED PROPERLY ; C=1 FAILURE, COMMON NOT LOADED PROPERLY ; S.PBIA IN SCB WITH BIAS OF PORT ;- CLASUP: CALL SAVREG ; SAVE REGISTERS 0-3 MOV S.PORT(R4),RADNAM ; GET RAD50 NAME OF PORT MOV #RADNAM,R3 ; NAME TO SEARCH FOR CALL @SRNAM ; SEARCH FOR PORT COMMON ; IF FOUND, R2 IS PCB ADDRESS BCS 20$ ; NO COMMON MOV R2,COMPCB ; SAVE PCB ADDRESS OF PORT COMMON MOV R2,R1 ; SAVE R2 BIT #PS.OUT,P.STAT(R1) ; PORT COMMON IN MEMORY ? BEQ 10$ ; YES MOVB #160.,P.PRI(R1) ; BRING IN COMMON QUICKLY CALL @LDREG ; BRING COMMON INTO MEMORY MOV COMPCB,R1 ; RESTORE PCB ADDRESS BR 20$ ; WE CAN'T WAIT FOR IT TO BE IN MEMORY 10$: INCB P.RMCT(R1) ; BUMP RESIDENT MAPPED TASK TASK COUNT BIS #PS.CHK!PS.FXD!PS.NSF,P.STAT(R1); MAKE NON-CHECKPOINTABLE ; FIXED IN MEMORY ; NON-SHUFFLEABLE BIS #P2.LMA,P.ST2(R1) ; DON'T TOUCH PARTITION MOV P.REL(R1),S.PBIA(R4) ; STORE BIAS OF PORT IN SCB CLC ; INDICATE NO ERROR RETURN 20$: MOVB #IE.PNT,@SCERR ; INDICATE PARTITION NOT THERE SEC ; INDICATE FAILURE RETURN .PAGE .SBTTL CLASYN - CLASS SYNCHRONIZATION ROUTINE ;+ ; **-CLASYN-CLASS SYNCHRONIZATION ROUTINE ; ; THIS ROUTINE IS CALLED BY THE PORT DRIVER FOR ONE OF TWO REASONS: ; HARDWARE SYNCHRONIZATION HAS COMPLETED SUCESSFULLY OR HADWARE ; SYNCHRONIZATION HAS FAILED. IF THE SYNCHRONIZATION WAS SUCESSFUL, ; THE CLASS DRIVER MUST ISSUE AN OP.SCC IMMEDIATELY AND PUT ALL UNITS ; INTO THEIR KNOWN STATES. ; ; INPUTS: ; ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; C=1 IF SYNCHRONIZATION FAILED ; C=0 IF SYNCHRONIZATION SUCEEDED ; ; OUTPUTS: ; ; R0-R1 ARE DESTROYED ; R2-R5 ARE PRESERVED ; ;- CLASYN: BCC 10$ ; IF CC, SYNCHRONIZATION SUCCEEDED JMP CLAERR ; JUMP TO ERROR ROUTINE ; ; SUCESSFUL COMPLETION OF HARDWARE SYNCHRONIZATION ; 10$: CLRB Q.IOSQ(R2) ; RESET SEQ NUM FOR THIS CONTROLLER BIS #C1.SCC,(R3) ; SCC STATE CALL PIOPAL ; ALLOCATE PSEUDO-IOP MOV #SCCFUN,R0 ; POINT TO TABLE ENTRY FOR SCC COMMANDS CALL CMDCOM ; GET A T/MSCP PKT. FILL IN SOME FIELDS ; R1 IS ADD OF PKT CLR P.HTMO(R1) ; SET HOST TIMEOUT .IF DF,E$$LOG MOV #CF.ATN!CF.MSC!CF.THS,P.CNTF(R1); ALL PACKETS BACK FROM CONTROLLER .IFF ;E$$LOG MOV #CF.ATN,P.CNTF(R1) ; ONLY ATTENTION MSG PACKETS .ENDC ;E$$LOG MOVB #10.,S.ITM(R4) ; TIMEOUT OF 10 SECONDS ON SCC COMMAND CALL CMDSEN ; SEND COMMAND TO CONTROLLER ; ; END PACKET PROCESSING ; ; INPUTS: ; R1-PTR TO END PACKET ; MOV R1,R0 ; COPY END PACKET ADDRESS ADD #P.CNTI,R0 ; POINT TO THE CONTROLLER CONTEXT MOV R2,R3 ; COPY QST ADDRESS ADD #Q.CNTI,R3 ; POINT TO CONTROLLER FIELDS MOV (R0)+,(R3)+ ; MOVE WORD OF CONTROLLER ID MOV (R0)+,(R3)+ ; MOVE WORD OF CONTROLLER ID MOV (R0)+,(R3)+ ; MOVE WORD OF CONTROLLER ID MOV (R0)+,(R3)+ ; MOVE WORD OF CONTROLLER ID MOVB P.CSVR(R1),(R3)+ ; MOVE CONTROLLER SOFTWARE VERSION MOVB P.CHVR(R1),(R3) ; MOVE CONTROLLER HARDWARE VERSION MOVB Q.ID(R2),CONEND ; MAKE SURE CONTROLLER MODEL FOUND MOV #CONTAB,R0 ; GET TABLE ADDRESS TO SCAN 12$: CMPB Q.ID(R2),(R0)+ ; CONTROLLER MODEL MATCH? BEQ 13$ ; YES. USE THAT INFORMATION TSTB (R0)+ ; SKIP OVER CONTROLLER INIT INFO BR 12$ ; CHECK ENTIRE TABLE 13$: MOVB (R0),Q.INF(R2) ; STORE THE INIT INFO IN QST .IF DF,T$$APE BIC #UU.BLK,U.UTIL(R5) ; ASSUME MULTI DENSITY DEVICE MOV #SNGDEN,R3 ; ADDRESS OF SPECIAL DRIVE/CONTROLLERS 14$: TSTB (R3) ; END OF TABLE? BLT 17$ ; YES. USE THE DEFAULT CMPB (R3)+,Q.CNTI+6(R2) ; IS IT A SPECIAL CONTROLLER? BNE 14$ ; NO. LOOK AT ANOTHER ENTRY BIS #UU.BLK,U.UTIL(R5) ; YES. MARK IT AS SINGLE DENSITY 17$: ; REFERENCE LABEL .ENDC ;T$$APE MOV (R2),R3 ; GET CST BACK MOV P.STS(R1),R0 ; GET STATUS/EVENT CODE BIC #^C,R0 ; CLEAR ALL BUT STATUS/EVENT BEQ 20$ ; IF EQ, YES ; ; SYNCHRONIZATION HAS FAILED ; SEC ; LOG ERROR JMP CLAERR ; SHOW ERROR. IF ANY RETRIES ARE LEFT ; A RETRY WILL BE INITIATED FROM THE ; TIMEOUT ROUTINE 20$: BIC #C1.SCC!C1.SYN,(R3) ; LEAVE FROM THE SCC AND SYN BIS #C1.RDY,(R3) ; AND GO TO THE RDY STATE .IF DF D$$DSK&DUTMO ; IF PRE-DEFINED TIMEOUT MOVB #DUTMO,S.ITM(R4) ; SET UP INITIAL TIMEOUT VALUE .IFF ; NORMAL CASE MOVB P.CTMO(R1),S.ITM(R4) ; SET-UP INITIAL TIMEOUT VALUE .ENDC ;D$$DSK&DUTMO BIT #C1.CON,(R3) ; IS THIS CON ONLINE FOR CONTROLLER? BEQ 40$ ; IF EQ, NO BIC #C1.CON,(R3) ; CLEAR OUT THE BIT MOVB #IS.SUC&377,@SCERR ; INDICATE SUCCESS OF CON ON_LINE MOV S.KRB(R4),R0 ; GET KRB ADDRESS MOV K.OWN(R0),R0 ; THE THE OWNING UCB BIT #UU.SPC,U.UTIL(R0) ; IS IT THE SPECIAL ONLINE? BEQ 30$ ; NO. DO THE DELAYED RETURN BIC #UU.SPC,U.UTIL(R0) ; CLEAR THE SPECIAL ONLINE BIT BR 40$ ; SKIP THE DELAYED RETURN 30$: PUSH ; SAVE REGISTERS TO BE SAFE MOV S.KRB(R4),R2 ; GET KRB BACK CALL @SAVSTK ; CALL EXEC ROUTINE TO INDICATE ; CON-ONLINE HAS FINISHED POP ; RESTORE REGISTERS 40$: MOV P.CRF+2(R1),R3 ; ADD OF PIOP MOV #IS.SUC,R0 ; TELL ENDCOM TO DEALLOCATE THE PIOP PUSH <#0> ; PUSH BYTE COUNT - FOR ENDCOM CALL ENDCMO ; PERFORM END PROCESSING CODE .IF DF,D$$DSK .IF NE,SPNTMO ; ; THE FOLLOWING CODE SCANS THE UCBS ON THIS CONTROLLER LOOKING FOR A SPECIFIC ; UNIT TYPE (IN THIS CASE RA81). IF ONE IS FOUND, THE UU.SER BIT FOR THAT ; UNIT IS SET SO THAT NO I/O'S WILL BE ACTIVATED FOR THAT UNIT. A TIMER IS ; SET SO THAT AFTER 'N' SECONDS, THE BIT GETS CLEARED AND I/O TO THAT UNIT ; WILL BE ALLOWED TO CONTINUE. A FORCED TIMEOUT WILL MAKE SURE IT HAPPENS. ; THE TIMER AND FORCED TIMEOUT WILL NOT OCCUR UNTIL THE CONTROLLER AND UNITS ; HAVE BEEN MSCP ONLINED AT LEAST ONCE SINCE IT IS THAT PROCESS WHICH FILLS ; IN THE UCB WITH THE DEVICE 'NAME'. ; DELAY: PUSH ; SAVE FIRST HALF OF REGISTERS CALL @ALCLK ; GET A CLOCK BLOCK BCS 110$ ; DID NOT GET ONE. SO, JUST GET OUT PUSH ; SAVE REGISTERS NEEDED DURING THIS PUSH <#0> ; COUNTER MOV #140000+X.NAME,R1 ; DEVICE NAME IN UCBX (APR 6 MAPPING) MOV S.KRB(R4),R2 ; GET KRB ADDRESS ADD K.OFF(R2),R2 ; POINT TO START OF UCB TABLE 10$: CMP (R2),#-1 ; END OF UCB TABLE? BEQ 20$ ; BRANCH IF SO MOV (R2)+,R3 ; GET NEXT UCB BITB #US.SPU,U.STS(R3) ; SPINNING UP? BEQ 10$ ; BRANCH IF NOT MOV U.UCBX(R3),@KISR6 ; MAP UCB EXTENSION CMP #^RRA8,(R1) ; RA81? (RAD50) BNE 10$ ; BRANCH IF NOT CMP #^R1 ,2(R1) ; RA81? (RAD50) BNE 10$ ; BRANCH IF NOT INC (SP) ; COUNT IT BISB #UU.SER,U.UTIL(R3) ; BLOCK OP.GUS FROM RECSIO BR 10$ ; ; SET UP CLOCK BLOCK IF RA81(S) WERE FOUND ; 20$: TST (SP)+ ; ANY RA81? BEQ 100$ ; BRANCH IF NOT PUSH ; SAVE WORK REGISTERS MOV @TKPS,R0 ; GET CLOCK RATE MOV #SPNTMO,R1 ; GET TIME OUT IN SECONDS CALL @MULS ; MULTIPLY MOV R1,R2 ; SWITCH TO REGS EXPECTED MOV R0,R1 ; BY $CLINS POP ; GET BACK CLOCK BLOCK ADDRESS MOV #TIMHAN,R3 ; CLOCK EXPIRATION HANDLER MOV R3,C.SUB(R0) ; CLOCK EXPIRATION HANDLER MOV S.KRB(R4),R5 ; SAVE KRB ADDRESS AS IDENTIFIER MOV #C.SYST,R4 ; CLOCK REQUEST TYPE - INTERNAL S/R CALL @CLINS ; PUT IN THE CLOCK QUEUE POP ; GET UCB, SCB ADDRESSES BACK 100$: POP <@KISR6,R3> ; GET MAPPING AND REGISTER BACK 110$: POP ; GET REST OF REGISTERS RESTORED JMP SKIP01 TIMHAN: PUSH ; SAVE REGISTERS / CURRENT MAPPING PUSH <#0> ; SET UP A COUNTER MOV #140000+X.NAME,R1 ; POINT TO DEVICE NAME IN UCBX MOV C.TCB(R4),R2 ; GET KRB ADDRESS ADD K.OFF(R2),R2 ; POINT TO START OF UCB TABLE 10$: CMP (R2),#-1 ; END OF UCB TABLE? BEQ 20$ ; BRANCH IF SO MOV (R2)+,R3 ; GET NEXT UCB BITB #US.SPU,U.STS(R3) ; SPINNING UP? BEQ 10$ ; BRANCH IF NOT MOV U.UCBX(R3),@KISR6 ; MAP ucb EXTENSION CMP #^RRA8,(R1) ; RA81? (RAD50) BNE 10$ ; BRANCH IF NOT CMP #^R1 ,2(R1) ; RA81? (RAD50) BNE 10$ ; BRANCH IF NOT INC (SP) ; COUNT IT BICB #UU.SER,U.UTIL(R3) ; UNBLOCK OP.GUS FROM RECSIO BR 10$ ; ; CONDITIONALLY SETUP DUDRV TIMEOUT IF RA81(S) WERE FOUND ; 20$: TST (SP)+ ; ANY RA81(S)? BEQ 30$ ; BRANCH IF NOT MOV C.TCB(R4),R2 ; GET KRB ADD K.OFF(R2),R2 ; POINT TO UCB TABLE MOV (R2),R3 ; GET A UCB MOV U.SCB(R3),R2 ; GET SCB TSTB S.CTM(R2) ; TIMEOUT IN PROGRESS? BNE 30$ ; BRANCH IF SO - IT'LL DO THE JOB INCB S.CTM(R2) ; SET A QUICK ONE UP TST S.BSYU(R2) ; GOT AN ACTIVE UNIT? BNE 30$ ; BRANCH IF SO - THAT'LL DO TOO MOV R3,S.BSYU(R2) ; SET AN 'ACTIVE' UNIT UP BISB #US.BSY,U.STS(R3) ; AND MARK IT BUSY ; ; DEALLOCATE CLOCK BLOCK AND RETURN ; 30$: POP <@KISR6,R3,R2,R1> MOV R4,R0 ; POINT TO CLOCK BLOCK CALLR @DECLK ; DEALLOCATE IT SKIP01: ; REFERENCE LABEL .ENDC ; SPNTMO .ENDC ;D$$DSK BIT #C1.REC,(R3) ; ARE WE IN RECOVERY? BEQ 50$ ; NO. JUST RETURN MOVB #1,S.CTM(R4) ; SET A 1 SECOND TIMEOUT COUNT TST S.BSYU(R4) ; IS A UNIT ALREADY BUSY? BNE 50$ ; YES. RETURN MOV R5,S.BSYU(R4) ; SET A BUSY UCB BISB #US.BSY,U.STS(R5) ; MARK IT AS BUSY 50$: RETURN .PAGE .SBTTL CMDCOM - ALLOCATE AND FILL IN COMMON COMMAND PACKET ;+ ; **-CMDCOM- ALLOCATE AND FILL IN COMMON COMMAND PACKET ; ; THIS ROUTINE ALLOCATES A COMMAND PACKET AND A RESPONSE PACKET ; FOR THE TMSCP/MSCP COMMAND ABOUT TO BE ISSUED. BEFORE THIS ; ROUTINE IS CLALED, PKTCHK MUST HAVE BEEN CALLED TO DETERMINE ; IS THERE ARE ENOUGH RESOURCES TO START THE TMSCP/MSCP I/O. TO ; HAVE REACHED THIS POINT, SUFFICIENT RESOURCES MUST EXIST. ; ; ONCE THE COMMAND PACKET IS ALLOCATED, THIS ROUTINE FILLS IN SOME ; OF THE COMMON FIELDS FOR VARIOUS ROUTINES. THE COMMAND PACKET, ; WHEN FIRST ALLOCATED, IS ZEROED OUT BEGINNING AT TEXT+0. ; ; INPUTS: ; ; R0 = FUNCTION DISPATCH TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0 = PRESERVED ; R1 = ADDRESS OF COMMAND PACKET ALLOCATED ; R2-R5 ARE PRESERVED ; ; THE FOLLOWING FIELDS ARE INITIALIZED IN THE COMMAND PACKET: ; P.CRF = COMMAND REFERENCE (PART 1) SET TO I/O SEQ NUMBER ; P.CRF+2 = COMMAND REFERENCE (PART 2) SET TO IOP ADDRESS ; P.UNIT = UNIT NUMBER SET TO U.UNIT(R5) ; P.OPCD = OPCODE SET TO FO.OP(R0) ; REST OF PACKET ZEROED OUT ;- CMDCOM: PUSH ; SAVE POINTER TO DISPATCH ENTRY MOVB FO.SZ(R0),R0 ; GET SIZE OF COMMAND PACKET CALLV PORT,PKTAC ; ALLOCATE/ZERO A COMMAND PACKET INCB Q.IOSQ(R2) ; INCR SEQ NUM FOR THIS CONTROLLER BICB #^C<17>,Q.IOSQ(R2) ; ONLY USE A FOUR BIT COUNTER BISB Q.IOSQ(R2),P.CRF(R1) ; USE AS COMMAND REFERENCE NUM 1 BICB #017,I.FLAG(R3) ; CLEAR OUT CRF IN IOP ;DC412 BISB P.CRF(R1),I.FLAG(R3) ; STORE THE ACTUAL COMMAND REF NUMBER ;DC412 MOV R3,P.CRF+2(R1) ; IOP ADDRESS IS SECOND CREF NUMBER ;**-2 BISB U.UNIT(R5),P.UNIT(R1) ; UNIT NUMBER (OBVIOUSLY 255 MAX) POP ; RESTORE DISPATCH ENTRY POINTER MOVB FO.OP(R0),P.OPCD(R1) ; OPCODE BIT #IQ.X,I.FCN(R3) ; INHIBIT ERROR RECOVERY? BEQ 10$ ; NO. BIS #MD.SER!MD.SEC,P.MOD(R1); INHIBIT IT THEN 10$: RETURN .PAGE .SBTTL CMDDAT - PROCESS ALL DATA TRANSFERS ;+ ; **-CMDDAT- PROCESS DATA TRANSFER REQUESTS. ; ; THIS SECTION DOES ALL THE PROCESSING SPECIFIC TO DATA TRANSFER REQUESTS. ; THERE ARE SEPARATE ENTRY POINTS FOR DIFFERENT FUNCTIONS. ANY SPECIFIC ; PROCESSING IS DONE AT EACH ENTRY POINT, AND THEN THEY ALL JOIN COMMON CODE. ; WHEN THE ROUTINE CMDSEN IS CALLED, THE PACKET IS SENT AND ; CONTROL IS RETURNED TO CLACMD TO PROCESS ANOTHER I/O. WHEN THE END PACKET ; IS RECEIVED, CONTROL IS RETURNED TO THIS ROUTINE IMMEDIATELY FOLLOWING THE ; CALL CMDSEN COMMAND. ; ; **-CMDCMP- COMPARE HOST DATA ENTRY POINT ; COMPARES DATA IN HOST BUFFER WITH DATA IN THE MU ; CONTROLLER BUFFER ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; DATA TRANSFER I/O STARTED ; R2-R5 PRESERVED ; ; FIRST CHECK FOR ANY ERROR CONDITIONS THAT WE CAN DETECT WITHOUT ; SENDING A COMMAND TO THE CONTROLLER. IF NO ERROR CONDITIONS ARE ; FOUND, GET AN MSCP PACKET, FILL IT IN, AND SEND IT OFF ; .IF DF D$$DSK .ENABL LSB CMDWDD: PUSH <#MD.CMP!MD.ERR> ; SET MODS TO WRITE DELETED DATA MARK BR 10$ ; SKIP OVER PUSHING 0 ON THE STACK CMDWPB: ;DC412 CMDWLB: PUSH <#0> 10$: BIT #DV.SWL,U.CW1(R5) ; IS THE UNIT SOFTWARE WRITE LOCKED? BEQ 20$ ; NO. CONTINUE MOV #IE.WLK&377,R0 ; SET UP WRITE LOCKED STATUS CODE BR CMDERR ; AND FINISH THE I/O CMDRPB: ;DC412 CMDRLB: PUSH <#0> 20$: BITB #IO.RPB&IO.WPB,I.FCN(R3); IS IT READ/WRITE PHYS. BLK? BNE 40$ ; YES. DON'T CHECK MAX LBN, SET MD.CMP .IF NDF DU$CHK ; BLOCK CHECKING DONE IN DUCHK IF Q OPT PUSH ; SAVE FUNCTION TABLE ADDRESS AND QST .IF DF,D$$PRT!E$$LBN ;DC412 MOV I.PRM+10(R3),R2 ; GET HIGH PART OF LBN ;DC412 .IFF ;DF, ;DC412 CLR R2 ; CLEAR HIGH BYTE ;DC412 BISB I.PRM+10(R3),R2 ; GET THE HIGH BYTE ;DC412 .ENDC ;DF, ;DC412 MOV I.PRM+12(R3),R0 ; GET LOW PART OF LBN ;**-1 MOV I.PRM+4(R3),R1 ; GET NUMBER OF BYTES TO TRANSFER ADD #777,R1 ; ROUND TO NEXT BLOCK ROR R1 ; CALCULATE #OF BLOCKS IN HIGH BYTE CLRB R1 ; CLEAR EXCESS BYTE SWAB R1 ; CALCULATE # OF BLOCKS IN TRANSFER ADD R1,R0 ; CALCULTE HIGHEST BLOCK NUMBER + 1 .IF DF,D$$PRT!E$$LBN ;DC412 BIT #DV.32B,U.CW1(R5) ; 32-BIT DEVICE ;DC412 BEQ 22$ ; IF NOT 32-BIT, CONTINUE ;DC412 ;DC412 ADC R2 ; ;DC412 BCS 25$ ; IF CS ILLEGAL BLOCK NUMBER ;DC412 CMP R2,U.CW2(R5) ; HIGH PART OF LBN LEGAL? ;DC412 BR 23$ ; REJOIN COMMON CODE ;DC412 22$: ; REFERENCE LABEL ;DC412 .ENDC ;DF, ;DC412 ADCB R2 ; BCS 25$ ; IF CS ILLEGAL BLOCK NUMBER CMPB R2,U.CW2(R5) ; HIGH PART OF LBN LEGAL? 23$: BHI 25$ ; IF HI NO ;DC412 BLO 30$ ; IF LO YES ;**-1 CMP R0,U.CW3(R5) ; LOW PART OF LBN LEGAL? BLOS 30$ ; IF LO OR SAME YES 25$: POP ; RESTORE QST AND FUNCTION TABLE ADDRESS MOV #IE.BLK&377,R0 ; SET UP THE STATUS CODE BR CMDERR ; AND EXIT 30$: POP ; RESTORE QST AND FUNCTION TABLE ADDRESS .ENDC ; DU$CHK BITB #IO.RLC&IO.WLC,I.FCN(R3); READ/WRITE CHECK FUNCTION? .IF DF D$$WCK ; IF DISK WRITECHECK BNE 40$ ; YES. SET THE CMP BIT CMPB #IO.WLB/256.,I.FCN+1(R3); IS THIS A WRITE REQUEST? BNE 50$ ; NO. DO NOT ATTEMPT TO SET MD.CMP BITB #US.WCK,U.STS(R5) ; DOES UNIT HAVE CHECK ENABLED? .ENDC ; D$$WCK BEQ 50$ ; NO. FORGET IT 40$: BIS #MD.CMP,(SP) ; SET THE BIT 50$: BIT #IQ.Q,I.FCN(R3) ; HOW ABOUT IQ.Q? BEQ CMDDAT ; NO. KEEP GOING BIS #MD.EXP,(SP) ; SET THE BIT BR CMDDAT .DSABL LSB .IFF ;D$$DSK CMDCMP: PUSH <#MD.CSE> ; CLEAR SERIOUS EXCEPTION CLEARED CMP I.PRM+4(R3),#2 ; SPECIAL CASE: RETURN IE.SPC ; TO TELL THAT IO.CMP SUPPORTED ; WITHOUT ACTUAL TAPE MOTION ; BEING DONE BGT CMDDAT ; NO - REAL COMMAND MOV #IE.SPC&377,R0 ; INDICATE A 'FAILURE' OF ; COMMAND TO FUNCTION BR CMDERR ; CLEAN UP AFTER REQUEST CMDWLB: PUSH <#MD.CSE> ; CLEAR SERIOUS EXCEPTION CMP I.PRM+4(R3),#14. ; ENOUGH BYTES FOR WRITE? BHIS 10$ ; IF HI YES MOV #IE.SPC&377,R0 ; SET UP BAD PARAMETERS ERROR BR CMDERR ; AND EXIT 10$: BIT #M.SWL,U.CW2(R5) ; IS THE UNIT SOFTWARE WRITE LOCKED? BEQ CMDDAT ; NO. CONTINUE MOV #IE.WLK&377,R0 ; SET UP WRITE LOCKED STATUS CODE BR CMDERR ; AND FINISH THE I/O CMDRLV: PUSH <#MD.REV!MD.CSE> ; SET MODIFIER TO READ REVERSE BR CMDDAT ; CONTINUE WITH COMMON CODE CMDRLB: PUSH <#MD.CSE> ; CLEAR SERIOUS EXCEPTION ON READ BR CMDDAT ; CONTINUE WITH COMMON CODE .ENDC ;D$$DSK CMDERR: TST (SP)+ ; CLEAR THE STACK CALLR CMDXIT ; AND EXIT CMDDAT: CALL CMDCOM ; GO GET A COMMAND PACKET BIS (SP)+,P.MOD(R1) ; ; IF WE NEED UMRS, ALLOCATE THEM FOR THE TRANSFER ; BIT #DV.EXT,U.CW1(R5) ; DO WE NEED UMRS? BNE 50$ ; NO. SKIP ALL THIS STUFF .IF DF M$$PRO BITB #IP.UMR,I.FLAG(R3) ; HAVE WE ALREADY ALLOCATED BLOCK ;DC412 BEQ 5$ ; NO. THEN WE MUST ;**-1 MOV (R2),R0 ; POINT TO CST MOVB I.PRM(R3),R2 ; GET UMR WAIT BLOCK POINTER ASL R2 ; MAKE A WORD OFFSET ADD R2,R0 ; ADD TO CST ADD #C.UMRW,R0 ; POINT TO UMR WAIT BLOCKS MOV (R0),R0 ; GET ADDRESS DEC R0 ; LOW BIT FLAG WAS SET - ODD ADDRESS BR 32$ ; ALREADY HAVE BLOCK--GO PAST ALLOCATION 5$: .ENDC ;M$$PRO PUSH ; SAVE THE COMMAND PACKET ADDRESS MOV (R2),R1 ; GET CST DEC C.UMCT(R1) ; DECREMENT THE UMR WAIT BLOCK COUNT ADD #C.UMRW,R1 ; POINT TO BEGINNING OF THE WAIT BLOCK MOV #-1,R2 ; COUNTER = -1 BECAUSE WE INCREMENT 10$: INC R2 ; INCREMENT THE INDEX COUNTER TST (R1) ; IS THERE A BLOCK HERE? BEQ 20$ ; IF EQ NO. ALLOCATE ANOTHER BIT #1,(R1)+ ; IS THE BLOCK IN USE? BNE 10$ ; YES. TRY ANOTHER MOV -(R1),R0 ; GET WAIT BLOCK BR 30$ ; GO TO COMMON CODE 20$: PUSH ; SAVE THE TABLE ADDRESS AND BLOCK INDEX MOV #UMRWTB,R1 ; SET LENGTH OF CORE BLOCK CALL @ALOCB ; GET A WAIT BLOCK POP ; RESTORE BLOCK INDEX AND TABLE ADDRESS BCC 25$ ; WE GOT ONE,OK MOV S.QST(R4),R2 ; GET QST MOV (R2),R1 ; GET CST INC C.UMCT(R1) ; NOT GOING TO USE WAIT BLOCK AFTER ALL POP ; GET BACK COMMAND PACKET MOV #IE.NDR&377,R0 ; SET NO DYNAMIC MEMORY CLR R1 ; JMP @IOFIN ; COMPLETE I/O WITH NO DYNAMIC MEMORY 25$: .IIF DF M$$PRO MOV S.URM(R4),(R0)+ ; PUT IN UNIBUS RUN MASK MOV R0,(R1) ; PUT THE NEW BLOCK ADDRESS IN THE TABLE 30$: INC (R1) ; SHOW THAT THE BLOCK IS IN USE POP ; GET BACK THE COMMAND PACKET MOVB R2,I.PRM(R3) ; SAVE UMR WAIT BLOCK INDEX IN IOP BISB #IP.UMR,I.FLAG(R3) ; MARK I/O AS HAVING A UMR WAIT BLOCK ;DC412 32$: MOV I.PRM(R3),U.BUF(R5) ; SET UP FOR UMR ASSIGNMENT BLOCK .. ;**-1 MOV I.PRM+2(R3),U.BUF+2(R5) ; ... PROCESSING OF BUFFER ADDRE MOV I.PRM+4(R3),U.CNT(R5) ; ... AND BYTE COUNT MOV S.QST(R4),R2 ; GET QST MOV (R2),R2 ; NOW THE CST BIS #C1.UMR,(R2) ; SHOW THAT WE ARE WAITING FOR A UMR MOV R0,R2 ; ... COPY UMR WAIT BLOCK POINTER TO R2 CALL @STMP1 ; SET UP UNIBUS MAPPING MOV S.PBIA(R4),@KISR6 ; MAKE SURE THE PORT IS STILL MAPPED MOV S.PBIA(R4),@#KINAR6 ; KERNAL INSTRUCTION SPACE MOV S.QST(R4),R0 ; GET QST MOV (R0),R0 ; NOW THE CST BIC #C1.UMR,(R0) ; CLR UMR MAPPING INTERLOCK ADD #10,R2 ; OFFSET TO UMR ASSIGNMENT BLOCK MOV R2,R0 ; ASSIGNMENT BLOCK WHERE $MPUB1 WANTS IT PUSH ; SAVE R1, POINTER TO UMR ASSIGN BLOCK CALL @MPUB1 ; MAP UNIBUS TO TRANSFER POP ; RESTORE PNTR TO UMR ASSIGN BLOCK, R1 MOV S.QST(R4),R2 ; GET QST BACK ALSO 50$: MOV I.PRM+2(R3),P.BUFF(R1) ; BUFFER DESCRIPTOR MOV I.PRM+4(R3),P.BCNT(R1) ; BYTE COUNT MOV I.PRM+10(R3),P.LBN+2(R1); HIGH BYTE OF LBN ;DC412 .IF DF,D$$PRT!E$$LBN ;DC412 BIT #DV.32B,U.CW1(R5) ; 32-BIT DEVICE? ;DC412 BNE 52$ ; IF NE, YES, CONTINUE ;DC412 .IFTF ;DF, ;DC412 CLRB P.LBN+3(R1) ; CLEAR THE HIGH BYTE ;DC412 .IFT ;DF, ;DC412 52$: ; REFERENCE LABEL ;DC412 .ENDC ;DF, ;DC412 MOV I.PRM+12(R3),P.LBN(R1) ; LOW WORD OF LBN ;**-1 MOVB I.PRM+1(R3),P.BUFF+2(R1); BUFFER DESCRIPTOR BIT #DV.EXT,U.CW1(R5) ; EXTENDED MEMORY SUPPORTED? BNE 55$ ; YES. NO MANIPULATION NECESSARY ;DC412 MOV M.UMVL(R0),P.BUFF(R1) ; LO 16 BITS ;**-1 MOVB M.UMVH(R0),P.BUFF+2(R1) ; HIGH 2 BITS ASR P.BUFF+2(R1) ; SHIFT BITS 4:5 TO 0:1 ASR P.BUFF+2(R1) ; ... ASR P.BUFF+2(R1) ; ... ASR P.BUFF+2(R1) ; ... BIC #^C<3>,P.BUFF+2(R1) ; CLEAR ALL BUT BITS 0:1 55$: .IF DF,D$$DSK&D$$PRT ;DC412 BIT #UU.PRT,U.UTIL(R5) ; PARTITIONED DRIVE? ;DC412 BEQ 60$ ; IF EQ, NOPE, CONTINUE ;DC412 ;DC412 BITB #IO.RPB&IO.WPB,I.FCN(R3) ; READ/WRITE PHYSICAL? ;DC412 BNE 60$ ; IF EQ, NOPE, MAKE IT PARTITION BIASED ;DC412 ;DC412 ADD U.PART+2(R5),P.LBN(R1) ; CONVERT I/O TO PARTITION BIAS ;DC412 ADC P.LBN+2(R1) ; DOUBLE PRECISION ;DC412 ADD U.PART+0(R5),P.LBN+2(R1) ; AND HIGH ORDER PART OF THE PACKET ;DC412 ;DC412 .ENDC ;DF,D$$DSK&D$$PRT ;DC412 ;DC412 60$: PUSH <#CLACMD> ; RETURN TO CLACMD CALL CMDSEN ; SEND OFF THE PACKET ; ; RETURN TO THIS POINT WITH END PACKET ; REGISTERS ARE THE SAME EXCEPT THAT R1 CONTAINS AN END PACKET INSTEAD OF A ; COMMAND PACKET ; ; NOW WE WILL FIND OUT HOW THE COMMAND FINISHED AND PUT THE STATUS CODE IN R0 ; FOR ENDCOM ; .IF DF D$$DSK CALL ENDERR ; TRANSLATE MSCP ERROR INTO RSX ERROR BITB #EF.BBR,P.FLGS(R1) ; BAD BLOCK REPORTED? BEQ 80$ ; NO ; ; WE'VE FOUND A BAD BLOCK. IF RCT IS NOT INSTALLED OR NOT APPLICABLE, ; WE JUST RETURN IE.BBE, BAD BLOCK ERROR. IF WE CAN USE RCT, THEN WE ; REQUEST IT TO RUN, AND PUT THE IOP IN THE BAD BLOCK QUEUE. ; RCT WILL REPLACE THE BLOCK AND THEN RETURN THE IOP TO US TO BE REISSUED ; (SEE CMDTRM) ; CALL RQRCT ; GO REQUEST RCT BCS 80$ ; IF CS, DON'T PUT I/O IN BBK QUEUE ; ; PUT THE IOP IN THE BAD BLOCK QUEUE AND SET UU.RCT ; PUSH ; SAVE THE IOP AND SHOW NO BYTE COUNT CLR R0 ; INDICATE NOT TO FINISH THE I/O CALL ENDCMO ; GO CLEAN UP THE I/O MOV (SP),R1 ; GET IOP BACK PUSH .IIF DF D$$DSK&DU$CHK CALL REQUE; RECONVERT THE LBN FOR QUEUE OPT. MOV R5,R0 ; PUT UCB WHERE $QINSF WANTS IT ADD #U.BPKT,R0 ; ADD OFFSET TO BAD BLOCK QUEUE CALL @QINSF ; PUT IT IN THE QUEUE AND EXIT POP ; RESTORE THEM RETURN 80$: PUSH ; SET BYTE COUNT FOR ENDCOM .IFF ;D$$DSK MOV P.STS(R1),R0 ; GET STATUS CODE BIC #^C,R0 ; CLEAR UNEEDED PORTION CMP #ST.SUC,R0 ; SUCCESSFUL? BNE 70$ ; NO. DON'T RESET ANYTHING BIC #M.BOT!M.PEOV!M.RWD!M.SER!M.TMK!M.EOT,U.CW2(R5) ; DEFAULTS ; ENDERR WILL DETECT BOT, EOT 70$: CALL ENDERR ; SET UP STATUS TO RETURN TO THE USER CMP #IS.SUC&377,R0 ; WAS IT SUCCESSFUL? BNE 80$ ; NO. BIC #M.AEOV,U.CW2(R5) ; NO LONGER AT LOGICAL EOT (TMK/TMK) 80$: PUSH ; USE ACTUAL TAPE RECORD BYTE COUNT ; THIS IS TO MAINTAIN COMPATABILITY ; WITH ALL OTHER RSX DRIVERS CMP I.FCN(R3),#IO.CMP ; COMPARE HOST DATA? BNE 85$ ; NO. RETURN ACTUAL TAPE ; RECORD COUNT MOV P.BCNT(R1),(SP) ; YES RETURN POINT OF MISMATCH ; (IF ANY) 85$: ; REFERENCE LABEL .ENDC ;D$$DSK CALLR ENDCOM ; FINISH THE I/O .PAGE .IF DF,T$$APE .SBTTL CMDEOF - PROCESS ROUTINE FOR IO.ERS, IO.EOF, AND IO.DSE ;+ ; **-CMDEOF-PROCESS ROUTINE FOR IO.EOF, IO.ERS, IO.DSE ; ; THIS ROUTINE ISSUES THE TMSCP REQUEST FOR IO.EOF (WRITE TAPE ; MARK), FOR IO.ERS (WRITE EXTENDED RECORD GAP) AND FOR IO.DSE ; (ERASE TO END OF TAPE). IF THE DRIVE IS SOFTWARE WRITE LOCKED, ; THE COMMAND IS NOT ISSUED AND AN ERROR IS RETURNED TO THE USER, ; OTHERWISE THE COMMAND IS ISSUED. ; ; NOTE: FOR EACH OF THESE FUNCTIONS, THE CURRENT TAPE POSITION IS ; USED. FOR IO.DSE, THE TAPE IS REPOSITIONED TO BOT AFTER ; ERASING TO THE END OF TAPE. ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; U.CW2(R5), M.SWL = FLAG INDICATING SOFTWARE WRITE LOCKED ; ; OUTPUTS: ; ; R0 = STATUS CODE ; R1 = STATUS INFORMATION (RETURNED AS ZERO) ; R2-R5 ARE PRESERVED ;- CMDEOF:: BIT #M.SWL,U.CW2(R5) ; IS UNIT SOFTWARE WRITE LOCKED? BEQ 10$ ; NO. GO SEND THE COMMAND MOV #IE.WLK&377,R0 ; WRITE LOCKED STATUS CODE CALLR CMDXIT ; COMMON ERROR EXIT 10$: BITB #US.MNT,U.STS(R5) ; IS IT MOUNTED? BEQ 20$ ; YES. OK TO DO THIS TYPE OF CMD MOV #IE.PRI&377,R0 ; ERROR. TAPE MUST BE MOUNTED CALLR CMDXIT ; COMMON ERROR EXIT 20$: CALL CMDCOM ; BUILD A SKELETON COMMAND PACKET BIS #MD.CSE,P.MOD(R1) ; SET 'CLR SER EXCEPTION' NO. PUSH <#CLACMD> ; RETURN ADDRESS CALL CMDSEN ; ISSUE THE COMMAND ; ; END PACKET PROCESSING. CONTROL RETURNS HERE WHEN THE END PACKET FOR ; THIS COMMAND IS RECEIVED. AT THIS POINT, THE I/O IS EFFECTIVELY DONE ; SO IT IS NECESSARY TO SET UP THE RETURN STATUS FOR THE USER, RETURN ; IT TO THEM, AND THEN CLEANUP FROM THE MSCP/TMSCP I/O. ; CALL ENDERR ; SET UP STATUS TO RETURN TO THE USER CMP R0,#IS.SUC&377 ; WAS THE COMMAND SUCCESSFUL? BNE 30$ ; NO. LEAVE STATES ALONE BIC #M.TMK!M.AEOV!M.BOT!M.RWD!M.SER!M.PEOV,U.CW2(R5) ; INDICATE STATE 30$: PUSH <#0> ; NO ADDITIONAL INFORMATION AVAILABLE CALLR ENDCOM ; CLEANUP FOLLOWING I/O COMPLETION .ENDC ;T$$APE .PAGE .IF DF D$$DSK .SBTTL CMDFMT - FORMAT ;+ ; **-CMDFMT-PROCESS ROUTINE FOR IO.SMD (FORMAT) ; ; THIS ROUTINE WILL PROCESS THE IO.SMD FUNCTION FOR DISKS THAT ; SUPPORT FORMATTING. ; ; BEFORE ISSUING THE FORMAT COMMAND IT ISSUES AVL COMMAND TO BRING ; THE UNIT TO UNIT AVAILABLE STATE AND AFTER FORMATING BRINGS THE ; THE UNIT BACK TO ONLINE STATE. ; ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0 = RSX STATUS CODE ; ; CMDFMT: BITB #US.FOR,U.STS(R5) ; IS THE DISK MOUNTED FOREIGN? BNE 2$ ; YES. THEN CONTINUE MOV #IE.PRI&377,R0 ; NO. THEN PRIVILEGE VIOLATION BR 5$ ; GO FINISH I/O 2$: BIT #DV.SWL,U.CW1(R5) ; IS THE UNIT SFT WRITE LOCKED ;DC412 BEQ 10$ ; EQ, THEN CONTINUE ;**-1 MOV #IE.WLK&377,R0 ; SET WRITE LOCK STATUS 5$: CALLR CMDXIT ; GO FINISH I/O 10$: MOVB Q.INF(R2),R0 ; GET CONTROLLER INFORMATION BIC #^C,R0 ; GET ONLY FORMAT SUPPORTED BNE 20$ ; CONTINUE CALLR ILEGAL ; NO. THEN IT IS ILLEGAL 20$: BIS #UU.SER,U.UTIL(R5) ; SET SERIAL MODE PUSH ; SAVE ORIG IOP ADDRESS CALL PIOPAL ; GET PIOP FOR AVL CMD POP ; STORE ORIG IOP ADDR IN PIOP MOV #AVNFUN,R0 ; FUNCTION CODE ENTRY TO USE CALL CMDCOM ; BUILD COMMAND PACKET BIS #MD.EXC,P.MOD(R1) ; SET EXCLUSIVE ACCESS PUSH <#CLACMD> ; ADDRESS TO RETURN TO CALL CMDSEN ; ISSUE COMMAND PUSH ; SAVE ORIG PIOP ADDR AGAIN MOV #IS.SUC,R0 ; NON ZERO STATUS TO R0 PUSH <#0> ; NO STATUS FOR IOSB CALL ENDCMO ; FINISH UP AVL COMMAND MOVB Q.INF(R2),R0 ; GET CONTROLLER INFORMATION BIC #^C,R0 ; GET ONLY FORMAT SUPPORTED CMP #FMSPC,R0 ; NEW FORMAT SUPPORT? BNE 23$ ; NO, SKIP THE ONLINE CALL PIOPAL ; GET PIOP FOR ONL CMD POP ; STORE ORIG IOP ADDR IN PIOP MOV #ONLFUN,R0 ; FUNCTION CODE ENTRY TO USE CALL CMDCOM ; BUILD COMMAND PACKET BIS #MD.IMF,P.MOD(R1) ; IGNORE MEDIA FORMAT ERROR PUSH <#CLACMD> ; ADDRESS TO RETURN TO CALL CMDSEN ; ISSUE COMMAND PUSH ; SAVE ORIG PIOP ADDR AGAIN MOV #IS.SUC,R0 ; NON ZERO STATUS TO R0 PUSH <#0> ; NO STATUS FOR IOSB CALL ENDCMO ; FINISH UP AVL COMMAND 23$: POP ; GET ORIG IOP ADDR MOV #FMTFUN,R0 ; FUNCTION CODE ENTRY TO USE CALL CMDCOM ; BUILD THE COMMAND PACKET MOVB Q.INF(R2),R0 ; GET CONTROLLER INFORMATION BIC #^C,R0 ; GET ONLY FORMAT SUPPORTED CMP R0,#FMDX3 ; OLD RQDX3 STYLE FORMAT? BNE 25$ ; NO. USE THE 'DEFAULT' MOVB #OP.SP8,P.OPCD(R1) ; USE THE RQDX3 OPCODE MOV I.PRM(R3),P.FMTI+2(R1) ; FILL THE FIRST 2 BYTES OF INFO MOV I.PRM+2(R3),P.FMTI(R1) ; FILL THE SECOND 2 BYTES OF INFO 25$: PUSH <#CLACMD> ; RETURN TO CLACMD CALL CMDSEN ; SEND OFF THE PACKET ; ; RETURN TO THIS POINT WITH END PACKET ; REGISTERS ARE THE SAME EXCEPT THAT R1 CONTAINS AN END PACKET ; INSTEAD OF A COMMAND PACKET. ; ; FIND OUT HOW THE COMMAND FINISHED AND PUT THE STATUS CODE IN ; R0 FOR ENDCOM AND BRING THE UNIT ONLINE. ; CALL ENDERR ; TRANSLATE MSCP STATUS TO RSX STATUS CMP #IS.SUC,R0 ; IS IT A SUCCESS BEQ 40$ ; YES THEN BRING THE UNIT ONLINE PUSH ; NEED TO USE R1, SO SAVE IT MOV P.STS(R1),R1 ; GET STATUS BIC #^C,R1 ; ISOLATE THE MAJOR STATUS CMP #ST.DRV,R1 ; IS IT A DRIVE ERROR BNE 30$ ; NO. CONTINUE MOV #IE.ABO&377,R0 ; YES. INDICATE FORMAT INCOMPLETE 30$: POP ; RESTORE END PACKET ADDRESS BIC #UU.SER,U.UTIL(R5) ; CLEAR THE SERIAL MODE PUSH <#0> ; NIL BYTE COUNT CALLR ENDCOM ; FINISH IT UP 40$: PUSH <#0> ; NIL BYTE COUNT CALL ENDCMO ; FINISH UP BIS #UU.ONL,U.UTIL(R5) ; INDICATE AN OP.ONL REQUIRED CALLR ONLSIO ; ISSUE THE ONLINE COMMAND .ENDC ;D$$DSK .PAGE .IF DF,D$$DSK .SBTTL CMDRPL - RCT BAD BLOCK REPLACEMENT ;+ ; **-CMDRPL- PROCESS BLOCK REPLACEMENT REQUESTS ; ; THIS ROUTINE PROCESSES BLOCK REPLACEMENT REQUESTS. ; ; INPUTS: ; ; R0 FUNCTION TABLE ENTRY ; R2 QST ADDRESS ; R3 IOP ADDRESS ; R4 SCB ADDRESS ; R5 UCB ADDRESS ; ; OUTPUTS: ; ;- CMDRPL: BIT #IQ.X!IQ.Q!IQ.UMD,I.FCN(R3) ; ILLEGAL SUBMODIFIERS BEQ CMDRP1 ; IT IS OK JMP ILEGAL ; EXIT WITH ILLEGAL FUNCTION CODE CMDRP1: CALL CMDCOM ; GET A COMMAND PACKET MOV I.PRM(R3),P.RBN+2(R1) ; REPLACEMENT BLOCK NUMBER MOV I.PRM+2(R3),P.RBN(R1) ; REPLACEMENT BLOCK NUMBER MOV I.PRM+4(R3),P.LBN+2(R1) ; LOGICAL BLOCK NUMBER MOV I.PRM+6(R3),P.LBN(R1) ; LOGICAL BLOCK NUMBER MOV I.PRM+10(R3),P.MOD(R1) ; MODIFIER MOV I.PRM+6(R3),I.PRM+12(R3); CLEAR SPACE FOR RETURN ADDRESS PUSH <#CLACMD> ; RETURN TO CLACMD CALL CMDSEN ; ISSUE THE RPL COMMAND ; ; RETURN TO THIS POINT WITH END PACKET ; MOV P.CRF+2(R1),R0 ; GET IOP ADDRESS MOV I.PRM+12(R0),I.PRM+6(R0); PUT THE LOGICAL BLOCK NUMBER BACK CALL ENDERR ; SET UP THE END CODE PUSH <#0> ; NO BYTE COUNT CALLR ENDCOM ; FINISH UP .PAGE .SBTTL CMDRSN - READ VOLUME SERIAL NUMBER ;+ ; **-CMDRSN-READ VOLUME SERIAL NUMBER ; ; THE READ VOLUME SERIAL ROUTINE WILL READ THE 4-BYTE VOLUME SERIAL NUMBER ; CONTAINED IN THE DEVICE'S SECOND UCB EXTENSION INTO A BUFFER SPECIFIED ; IN THE IOP. ; ; INPUTS: ; ; R0 FUNCTION TABLE ENTRY ; R2 QST ADDRESS ; R3 IOP ADDRESS ; R4 SCB ADDRESS ; R5 UCB ADDRESS ; ; OUTPUTS: ; ; R0 SUCCESS CODE ; R1 BYTES TRANSFERED ; R2-R5 PRESERVED ;- CMDRSN: BITB #IQ.X!IQ.Q!IQ.UMD,I.FCN(R3) ; DO WE HAVE ANY ILLEGAL MODIFIERS? BEQ 10$ ; NO. CONTINUE CALLR ILEGAL ; ILLEGAL FUNCTION CODE 10$: CMP I.PRM+4(R3),#R$MSIZ ; IS IT IN RANGE? BLE 20$ ; NO. RETURN ERROR MOV #IE.BAD&377,R0 ; BAD LENGTH SPECIFIED CALLR CMDXIT ; COMMON ERROR PROCESSING 20$: PUSH ; SAVE WORK REGISTERS ; ; MAP UCB EXTENSION AND MOVE SELECTED FIELDS INTO PACKET ; MOV U.UC2X(R5),@KISR6 ; MAP EXTENSION THROUGH APR 6 MOV #RSNEXP,R2 ; TEMP AREA FOR PACKET MOV X.VSER+140000,(R2)+ ; PART 1 OF VERSION NUM : R$VRSN MOV X.VSER+2+140000,(R2)+ ; PART 2 OF VERSION NUM : R$VRSN+2 MOV X.UNFL+140000,(R2)+ ; UNIT FLAGS : R$USTA ; MOV #RSNEXP+R$UNTI,R2 ; UNIT INFO POINTER MOV X.UNTI+140000,(R2)+ ; PART 1 OF UNIT ID : R$UNTI MOV X.UNTI+2+140000,(R2)+ ; PART 2 OF UNIT ID : R$UNTI+2 MOV X.UNTI+4+140000,(R2)+ ; PART 3 OF UNIT ID : R$UNTI+4 MOV X.UNTI+6+140000,(R2)+ ; PART 4 OF UNIT ID : R$UNTI+6 MOVB X.USVR+140000,(R2)+ ; UNIT SOFT VERS : R$USVR MOVB X.UHVR+140000,(R2)+ ; UNIT HARD VERS : R$UHVR MOV X.MLUN+140000,(R2)+ ; MULTI UNIT CODE : R$MLUN CLR (R2)+ ; COMMAND REFERENCE NUM 1: R$CRF CLR (R2)+ ; COMMAND REFERENCE NUM 2: R$CRF+2 CLR (R2)+ ; SEQUENCE NUMBER : R$SEQ CLR (R2) ; EVENT CODE : R$OPCD ; ; RESTORE PUCOM MAPPING AND COMPLETE THE PACKET PROCESSING ; MOV S.PBIA(R4),@KISR6 ; REMAP PUCOM MOV (SP),R2 ; GET QST ADDR BACK ADD #Q.CNTI,R2 ; POINT TO ORIGINAL INF MOV #RSNEXP+R$CNTI,R4 ; POINT TO CONTROLLER INF MOV (R2)+,(R4)+ ; CONTROLLER INFORMATION : R$CNTI MOV (R2)+,(R4)+ ; CONTROLLER INFORMATION : R$CNTI+2 MOV (R2)+,(R4)+ ; CONTROLLER INFORMATION : R$CNTI+4 MOV (R2)+,(R4)+ ; CONTROLLER INFORMATION : R$CNTI+6 MOV (R2),(R4) ; CNTRL SOFT/HARD INFO : R$CXVR ; ; RETURN PACKET TO THE USER BUFFER ; MOVB I.PRM+1(R3),R2 ; SET HI 6-BITS OF ADDRESS MOV I.PRM+2(R3),R3 ; SET LO 16-BITS OF ADDRESS ASHC #10.,R2 ; CALCULATE DISPLACEMENT AND BIAS ASHC #-10.,R3 ; ... MOV R3,R4 ; COPY DESTINATION DISPLACEMENT INTO R4 BIS #140000,R4 ; SET DESTINATION BIAS FOR APR6 MOV R2,R3 ; COPY DESTINATION BIAS INTO R3 MOV 2(SP),R0 ; GET IOP ADDRESS MOV I.PRM+4(R0),R0 ; GET NUMBER OF BYTES FROM USER MOV @KISR5,R1 ; SOURCE BIAS MOV #RSNEXP,R2 ; GET SOURCE DISPLACMENT CALL @BLXIO ; MOVE THE DATA TO USER BUFFER POP ; RESTORE ORIGNAL CONTENTS MOV I.PRM+4(R3),R1 ; BYTE COUNT MOV #IS.SUC&377,R0 ; RETURN SUCCESS PUSH <#CLACMD> ; START ANOTHER COMMAND IF POSSIBLE CALLR ENDCM1 ; COMPLETE THE IOP PROCESSING .ENDC ;D$$DSK .PAGE .IF DF,T$$APE .SBTTL CMDRWD - PROCESS ROUTINE FOR IO.RWD AND IO.RWU FUNCTIONS ;+ ; **-CMDRWD-ROUTINE TO HANDLE REWIND FUNCTION ; ; THIS ROUTINE WILL PROCESS THE RSX IO.RWD AND IO.RWU FUNCTIONS FOR TAPES ; ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0 = STATUS CODE ; R2-R5 ARE PRESERVED ; U.CW2, BIT M.AEOV CLEAR ON SUCCESSFUL REWIND OPERATION ; U.CW2, BIT M.REW SET TO INDICATE TAPE IS REWINDING ; U.STS, BIT US.PWF CLEAR POWERFAIL BIT TO ALLOW COMMANDS ; ; ; THE VALUE TO PUT INTO IOSB+2 IS ON THE STACK FOR ENDCOM ;- CMDRWU: PUSH <#MD.UNL!MD.CSE> ; UNLOAD AND 'CLR SER EXCEPT' MODIFIERS BR CMDRWC ; JOIN COMMON CODE CMDRWD: PUSH <#MD.RWD!MD.IMM!MD.CSE>; SET REWIND, IMMEDIATE, AND ; 'CLR SER EXCEPT' MODIFIERS CMDRWC: ; COMMON ENTRY POINT CALL CMDCOM ; ALLOCATE T/MSCP PACKET AND FILL ; COMMAND FIELDS BIS (SP)+,P.MOD(R1) ; SET THE MODIFIERS PUSH <#CLACMD> ; SAVE ROUTINE ADD ON STACK CALL CMDSEN ; SEND COMMAND TO CONTROLLER ; ; END PACKET PROCESSING ; BICB #EF.EOT,P.FLGS(R1) ; DO NOT USE EOT FLAG ON REWINDS MOV P.CRF+2(R1),R0 ; GET I/O PACKET ADDRESS MOV I.FCN(R0),R0 ; GET I/O FUNCTION CODE BIC #IQ.Q!IQ.X!IQ.UMD,R0 ; CLEAR SPECIAL MODIFIERS CMP R0,#IO.RWU ; REWIND/UNLOAD COMMAND? BNE 2$ ; NO. DO NOT CHANGE TO SUCCESS CMP #ST.VOL,P.STS(R1) ; VOLUME MOUNTED? BEQ 3$ ; NOTHING THERE; SHOW SUCCESS 2$: ; REFERENCE LABEL CMP #ST.AVL,P.STS(R1) ; UNIT AVAILABLE? BNE 5$ ; NO. 3$: CLR P.STS(R1) ; INDICATE SUCCESS (ST.SUC) 5$: CALL ENDERR ; SET UP STATUS TO RETURN TO USER CMP #IS.SUC&377,R0 ; WAS IT SUCCESSFUL? BNE 10$ ; NO BISB #US.PWF,U.STS(R5) ; SET POWERFAIL BIT BIC #M.PEOV!M.RWD!M.SER!M.TMK!M.EOT!M.AEOV,U.CW2(R5) ; NEW STATES BIS #M.BOT,U.CW2(R5) ; INDICATE TAPE IS AT BOT (OR WILL BE ; WHEN THE CONTROLLER GETS DONE WITH IT) 10$: PUSH <#0> ; VALUE TO PUT INTO IOSB+2 CALLR ENDCOM ; DO COMMON END PROCESSING .PAGE .SBTTL CMDSMO - MOUNT AND SET TAPE CHARACTERISTICS ;+ ; **-CMDSMO-PROCESS ROUTINE FOR IO.SMO (MOUNT AND SET CHARACTERISTICS) ; ; THIS ROUTINE PERFORMS THE FUNCTION OF SETTING THE TAPE CHARACTERISTICS AND ; BRINGING THE UNIT TMSCP ONLINE. FOR TAPES THAT SUPPORT MULTIPLE DENSITIES, ; THIS MUST FIRST MAKE SURE THE TAPE UNIT IS TMSCP AVAILABLE. IF IT IS NOT, ; AN AVAILABLE COMMAND MUST BE ISSUED, FOLLOWED BY AN ONLINE COMMAND SO THAT ; THE TAPE DENSITY CAN BE SET TO THAT SPECIFIED BY THE USER. ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0 = STATUS CODE ; R1 = DESTROYED ; R2-R5 ARE PRESERVED ;- CMDSMO: BIT #M.BOT,U.CW2(R5) ; ARE WE AT BEGINNING OF TAPE? BNE 10$ ; YES. CONTINUE WITH DENSITY SETTING CALLR ILEGAL ; NO. IO.SMO IS ILLEGAL THEN 10$: BIT #UU.BLK,U.UTIL(R5) ; DOES UNIT SUPPORT MULTIPLE DENSITIES? BNE 200$ ; NO. NOTHING TO DO IN HERE PUSH ; SAVE ORIG IOP ADDR CALL PIOPAL ; A "FALSE" IOP FOR AVN COMMAND POP ; SAVE ORIG IOP ADDR IN PIOP MOV #AVNFUN,R0 ; FUNCTION CODE ENTRY TO USE CALL CMDCOM ; BUILD TEMPLATE COMMAND BIS #MD.CSE,P.MOD(R1) ; SET 'CLEAR SERIOUS EXCEPTION' MODIFIER PUSH <#CLACMD> ; WHERE TO RETURN TO CALL CMDSEN ; ISSUE THE COMMAND PUSH ; SAVE WHAT WILL BE USED LATER PUSH ; SAVE ORIG IOP ADDR MOV #IS.SUC,R0 ; NON-ZERO -> RETURN IOP TO POOL PUSH <#0> ; NO IOSB DATA EITHER CALL ENDCMO ; CLEAN UP PACKET USED POP ; RESTORE ORIG IOP ADDR POP ; RETURN REGISTERS 200$: CALLR CMDONL ; ISSUE THE ONLINE COMMAND .PAGE .SBTTL CMDSPB - PROCESS ROUTINE FOR IO.SPB ;+ ; **-CMDSPB-PROCESS ROUTINE FOR IO.SPB (SPACE BLOCKS) ; ; THIS ROUTINE PERFORMS THE FUNCTION OF SPACING FORWARD OR BACKWARD OVER ; A SPECIFIED NUMBER OF BLOCKS. IF A NEGATIVE BLOCK COUNT IS ; SPECIFIED, THE SKIPPING IS DONE IN THE REVERSE DIRECTION. FOR UNLABELED ; TAPE, SPACING BLOCKS PAST EOV (TWO CONSECUTIVE TAPE MARKS OR BOT/TMRK) ; IS NOT PERMITTED. ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; U.CW2, BIT M.AEOV=TAPE AT OR PAST LOGICAL EOT ; ; OUTPUTS: ; ; R0 = STATUS CODE ; R1 = STATUS INFORMATION (NUMBER OF BLOCKS SKIPPED) ; R2-R5 ARE PRESERVED ; U.CW2, BIT M.AEOV=TAPE AT OR PAST LOGICAL EOT ;- CMDSPB:: TST I.PRM(R3) ; ANY BLOCKS ACTUALLY SPECIFIED? BNE 10$ ; YES. FURTHER PROCESSING NEEDED MOV #IS.SUC&377,R0 ; INDICATE SUCCESS (NOP THE I/O) CALLR CMDXIT ; COMMON ERROR EXIT 10$: BITB #US.MNT,U.STS(R5) ; IS THE UNIT MOUNTED? BEQ 20$ ; YES. OK TO DO THIS TYPE OF CMD MOV #IE.PRI&377,R0 ; ERROR. TAPE MUST BE MOUNTED CALLR CMDXIT ; COMMON ERROR EXIT 20$: BITB #US.LAB,U.STS(R5) ; WORKING WITH A LABELED TAPE? BNE 30$ ; YES. SKIP LOGICAL EOV CHECKS BIT #M.AEOV,U.CW2(R5) ; ARE WE PAST LOGICAL END OF TAPE BEQ 30$ ; NO. GO TO COMMON PROCESSING TST I.PRM(R3) ; TEST SPACING DIRECTION BLE 30$ ; BACKWARD IS OK. MOV #IE.EOV&377,R0 ; INDICATE EOV ON UNLABELED TAPE CALLR CMDXIT ; COMMON ERROR EXIT 30$: CALL CMDCOM ; BUILD A SKELETON COMMAND PACKET BIS #MD.CSE,P.MOD(R1) ; SET 'CLR SER EXCEPT' MODIFIER CLR P.RECC+2(R1) ; HIGH ORDER WORD OF BLOCK COUNT MOV I.PRM(R3),P.RECC(R1) ; DEFAULT SPACE BLOCK COUNT BGE 40$ ; GOING FORWARD DIRECTION. BIS #MD.REV,P.MOD(R1) ; INDICATE REVERSE DIRECTION NEG P.RECC(R1) ; INDICATE POSITIVE NUMBER OF BLOCKS 40$: BITB #US.LAB,U.STS(R5) ; IS THIS LABELED TAPE? BNE 50$ ; YES. SKIP LEOT PROCESSING TST I.PRM(R3) ; FORWARD DIRECTION? BLE 50$ ; NO. SKIP LEOT PROCESSING BIS #MD.DLE,P.MOD(R1) ; SET TO DETECT LEOT FOR UNLABELED TAPES 50$: CLR P.TMGC(R1) ; INSURE NO TAPE MARKS WILL BE SKIPPED CLR P.TMGC+2(R1) ; HIGH ORDER WORD OF TAPE MARK COUNT PUSH <#CLACMD> ; RETURN ADDRESS CALL CMDSEN ; ISSUE TMSCP COMMAND ; ; END PACKET PROCESSING. CONTROL RETURNS HERE WHEN THE END PACKET FOR ; THIS COMMAND IS RECEIVED. AT THIS POINT, THE I/O IS EFFECTIVELY DONE ; SO IT IS NECESSARY TO SET UP THE RETURN STATUS FOR THE USER. OTHER ; FLAGS HAVE TO BE SET TO SHOW THE RESULT OF THE OPERATION. ; CALL ENDERR ; GET RSX STATUS CODE BIC #M.AEOV,U.CW2(R5) ; ASSUME NO LONGER AT END OF VOLUME CMP R0,#IE.EOV&377 ; WAS LEOT ENCOUNTERED? BNE 60$ ; NO. BIS #M.AEOV,U.CW2(R5) ; INDICATE THAT LOGICAL EOT HIT BIC #M.BOT!M.PEOV!M.RWD!M.SER!M.TMK!M.EOT,U.CW2(R5) ; NEW STATES 60$: PUSH ; NUMBER OF BLOCKS SKIPPED CMP R0,#IE.EOF&377 ; WAS A TAPE MARK ENCOUNTERED? BNE 70$ ; NO. INC (SP) ; COUNT TAPE MARK AS BLOCK SKIPPED 70$: CALLR ENDCOM ; GO TO COMMON CLEANUP CODE .PAGE .SBTTL CMDSPF - PROCESS ROUTINE FOR IO.SPF ;+ ; **-CMDSPF-PROCESS ROUTINE FOR IO.SPF (SPACE FILES) ; ; THIS ROUTINE PERFORMS THE FUNCTION OF SPACING FORWARD OR BACKWARD OVER ; A SPECIFIED NUMBER OF TAPE MARKS. IF A NEGATIVE TAPE MARK COUNT IS ; SPECIFIED, THE SKIPPING IS DONE IN THE REVERSE DIRECTION. FOR UNLABELED ; TAPE, SPACING FILES PAST EOV (TWO CONSECUTIVE TAPE MARKS OR BOT/TMRK) ; IS NOT PERMITTED. ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; U.CW2, BIT M.AEOV=TAPE AT OR PAST LOGICAL EOT ; ; OUTPUTS: ; ; R0 = STATUS CODE ; R1 = STATUS INFORMATION (NUMBER OF FILES SKIPPED) ; R2-R5 ARE PRESERVED ; U.CW2, BIT M.AEOV=TAPE AT OR PAST LOGICAL EOT ;- CMDSPF:: TST I.PRM(R3) ; ANY TAPE MARKS ACTUALLY SPECIFIED? BNE 10$ ; YES. FURTHER PROCESSING NEEDED MOV #IS.SUC&377,R0 ; INDICATE SUCCESS (NOP THE I/O) CALLR CMDXIT ; COMMON ERROR EXIT 10$: BITB #US.MNT,U.STS(R5) ; IS THE UNIT MOUNTED? BEQ 20$ ; YES. OK TO DO THIS TYPE OF CMD MOV #IE.PRI&377,R0 ; ERROR. TAPE MUST BE MOUNTED CALLR CMDXIT ; COMMON ERROR EXIT 20$: BITB #US.LAB,U.STS(R5) ; WORKING WITH A LABELED TAPE? BNE 30$ ; YES. SKIP LOGICAL EOV CHECKS BIT #M.AEOV,U.CW2(R5) ; ARE WE PAST LOGICAL END OF TAPE BEQ 30$ ; NO. GO TO COMMON PROCESSING TST I.PRM(R3) ; TEST SPACING DIRECTION BLE 30$ ; BACKWARD IS OK. MOV #IE.EOV&377,R0 ; INDICATE EOV ON UNLABELED TAPE CALLR CMDXIT ; COMMON ERROR EXIT 30$: CALL CMDCOM ; BUILD A SKELETON COMMAND PACKET BIS #MD.CSE,P.MOD(R1) ; SET 'CLR SER EXCEPT' MODIFIER CLR P.TMGC+2(R1) ; HIGH ORDER WORD OF TAPE MARK COUNT MOV I.PRM(R3),P.TMGC(R1) ; DEFAULT SPACE FILE COUNT BGE 40$ ; GOING FORWARD DIRECTION. BIS #MD.REV,P.MOD(R1) ; INDICATE REVERSE DIRECTION NEG P.TMGC(R1) ; INDICATE POSITIVE NUMBER OF TMRKS 40$: BITB #US.LAB,U.STS(R5) ; IS THIS LABELED TAPE? BNE 50$ ; YES. SKIP LEOT PROCESSING TST I.PRM(R3) ; FORWARD DIRECTION? BLE 50$ ; NO. SKIP LEOT PROCESSING BIS #MD.DLE,P.MOD(R1) ; SET TO DETECT LEOT FOR UNLABELED TAPES 50$: CLR P.RECC(R1) ; INSURE NO BLOCKS WILL BE SKIPPED CLR P.RECC+2(R1) ; HIGH ORDER WORD OF BLOCK COUNT PUSH <#CLACMD> ; RETURN ADDRESS CALL CMDSEN ; ISSUE TMSCP COMMAND ; ; END PACKET PROCESSING. CONTROL RETURNS HERE WHEN THE END PACKET FOR ; THIS COMMAND IS RECEIVED. AT THIS POINT, THE I/O IS EFFECTIVELY DONE ; SO IT IS NECESSARY TO SET UP THE RETURN STATUS FOR THE USER. OTHER ; FLAGS HAVE TO BE SET TO SHOW THE RESULT OF THE OPERATION. ; CALL ENDERR ; GET RSX STATUS CODE BIC #M.AEOV,U.CW2(R5) ; ASSUME NO LONGER AT END OF VOLUME CMP R0,#IE.EOV&377 ; WAS LEOT ENCOUNTERED? BNE 60$ ; NO. BIS #M.AEOV,U.CW2(R5) ; INDICATE THAT LOGICAL EOT HIT BIC #M.PEOV!M.BOT!M.RWD!M.SER!M.TMK!M.EOT,U.CW2(R5) ; NEW STATE 60$: PUSH ; NUMBER OF TAPE MARKS SKIPPED CALLR ENDCOM ; GO TO COMMON CLEANUP CODE .ENDC ;T$$APE .PAGE .SBTTL CMDXIT - COMMON ERROR EXIT - INCLUDES ILEGAL EXIT ;+ ; ; **-ILEGAL-EXIT WITH ILLEGAL FUNCTION CODE ; **-CMDXIT-COMMON ERROR EXIT ; ; THIS ROUTINE PROVIDES A SIMPLE AND COMMON EXIT PATH FOR COMMAND ERRORS ; THAT ARE DETECTED BEFORE ANY I/O IS ACTUALLY ISSUED TO THE CONTROLLER ; ; INPUTS: ; ; R0 = RSX ERROR CODE TO BE RETURNED ; ; OUTPUTS: ; ; CONTROL IS PASSED TO ENDCM1 ; ;- ILEGAL: MOV #IE.IFC&377,R0 ; ILLEGAL FUNCTION CODE CMDXIT: CLR R1 ; NO BYTE COUNT PUSH <#CLACMD> ; RETURN TO CLACMD TO FIND MORE TO DO CALLR ENDCM1 ; JOIN COMMON END PROCESSING .PAGE .SBTTL CMDSEN - SEND OFF COMMAND PACKET ;+ ; **-CMDSEN-ROUTINE TO SEND CMD PKT AND ADD IOP TO C.OLHD QUEUE ; ; THIS ROUTINE WILL SEND THE T/MSCP PACKET TO THE CONTROLLER. ; IT ALSO WILL ADD THE IOP TO THE END OF THE OUTSTANDING QUEUE. ; IF THE COMMAND IS THE OLDEST, THEN THE COMMAND STATUS IS UPDATED ; AND THE TIMEOUT COUNT IS UPDATED AND THE TIMER GETS STARTED. ; ; INPUTS: ; ; R1 = COMMAND PACKET ADDRESS ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0-R1-R3 DESTROYED ; R2-R4-R5 PRESERVED ;- CMDSEN: POP ; ADDR TO RETURN TO WHEN END PKT ARRIVES CALLV PORT,PORSEN ; SEND CMD PKT TO CONTROLLER MOV (R2),R0 ; ADDR OF CST ADD #C.OLHD,R0 ; POINT TO QUEUE OF OUTSTANDING IOPS MOV R3,R1 ; POINTS TO IOP TO ADD CALL @QINSF ; INSERT IOP INTO QUEUE ; R2 GETS DESTROYED MOV S.QST(R4),R2 ; RESTORE THE QST ADDRESS MOV R3,R0 ; IOP ADDRESS MOV (R2),R3 ; ADDR OF CST CMP R0,C.OLHD(R3) ; IS THIS COMMAND NOW THE OLDEST ? BNE 20$ ; NO ; ; RESET TIMEOUT COUNT FOR NEW OLDEST COMMAND AND MAYBE RESET BSYUCB ; MOVB S.ITM(R4),S.CTM(R4) MOV S.BSYU(R4),R1 ; ADDRESS OF THE PREVIOUS BUSY UNIT BEQ 10$ ; IF NO UNIT IS BUSY CHANGE BSYUCB BICB #US.BSY,U.STS(R1) ; CLEAR BUSY BIT ON OLD BUSY UNIT 10$: BISB #US.BSY,U.STS(R5) ; SET BUSY BIT ON NEW BUSY UNIT MOV R5,S.BSYU(R4) ; CHANGE BSYUCB MOV #-1,C.CMST(R3) ; SET COMMAND STATUS PROGRESS TO MAX MOV #-1,C.CMST+2(R3) ; UNSIGNED DOUBLE PRECISION 20$: RETURN ; RETURN TO CALLER'S CALLER .PAGE .SBTTL CMDSIO - START NEXT I/O REQUEST ;+ ; **-CMDSIO-TRY TO START NEXT I/O REQUEST FROM SCB QUEUE ; ; THIS ROUTINE WILL TRY TO START THE NEXT I/O REQUEST FROM THE SCB ; QUEUE. THIS ROUTINE WILL DISPATCH TO THE FUNCTION CODE SPECIFIC ; ROUTINE WHICH WILL RETURN TO CLACMD. ; ; INPUTS: ; ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0 = FUNCTION CODE ENTRY IN TABLE ; R1 = DESTROYED ; R3 = IOP ADDRESS ; R2-R4-R5 ARE PRESERVED ; ;- CMDSIO: MOV #XXACC,R2 ; ADDRESS OF ACCEPTANCE ROUTINE ; ; MAKE BUSY UNIT TEMPORARILY NON-BUSY ; IT IS ONLY BUSY SO THAT THE TIMEOUT COUNT IN THE SCB IS DECREMENTED. ; MOV S.BSYU(R4),R0 BEQ 10$ BICB #US.BSY,U.STS(R0) 10$: .IF DF D$$DSK BISB #C2.SHD,C.FLAG(R3) ; SET RECURSIVE FLAG .IFTF ;D$$DSK CALL @GSPKT ; GET IOP TO PROCESS ; ; MAKE BUSY UNIT BUSY AGAIN ; MOV S.QST(R4),R2 ; WE NEED THE QST .IFT ;D$$DSK MOV (R2),R3 ; GET CST BICB #C2.SHD,C.FLAG(R3) ; CLEAR THE RECURSION FLAG .ENDC ;D$$DSK MOV S.BSYU(R4),R0 BEQ 20$ BISB #US.BSY,U.STS(R0) 20$: .IF DF D$$DSK&DU$CHK ; IF QUEUE OPTOMIZATION SUPPORTED BCS 30$ ; IF CS, NO PACKETS LEFT, EXIT ; ; UNFORTUNATELY WE NOW HAVE TO CHANGE SECTOR, TRACK, AND CYLINDER THAT QUEUE ; OPTOMIZATION NEEDED BACK INTO AN LBN NUMBER. ; CMPB #IO.RLB/256.,I.FCN+1(R1); DATA TRANSFER REQUEST? BLO CMDRED ; IF LO NO. LEAVE IT ALONE MOV I.PRM+10(R1),R2 ; GET CYLINDER NUMBER MOVB U.PRM+1(R5),R0 ; GET TRACKS/CYLINDER MUL R0,R2 ; TRACKS UP TO CURRENT CYLINDER MOVB I.PRM+13(R1),R2 ; GET CURRENT TRACK NUMBER ADD R3,R2 ; GET CURRENT TRACK MOVB U.PRM(R5),R0 ; GET SECTORS/TRACK MUL R0,R2 ; SECTORS UP TO CURRENT TRACK MOVB I.PRM+12(R1),R0 ; GET CURRENT SECTOR ADD R0,R3 ; GET TOTAL SECTOR NUMBER ADC R2 ; HIGH AND LOW MOV R2,I.PRM+10(R1) ; SAVE HIGH LBN NUMBER MOV R3,I.PRM+12(R1) ; SAVE LOW LBN NUMBER MOV S.QST(R4),R2 ; GET QST BR CMDRED ; GO PROCESS THE PACKET 30$: .IFF BCC CMDRED .ENDC ;D$$DSK&DU$CHK MOV (R2),R3 ; GET CST BIT #C1.DQU,(R3) ; SHOULD WE CALL $DQUMR? BEQ 40$ ; IF EQ NO BIC #C1.DQU,(R3) ; CLEAR THE BIT OUT ; ; DO NOT CHANGE THE FOLLOWING CALL AND RETURN TO A JUMP: $DQUMR IS A COROUTINE ; CALL @DQUMR ; AND CALL IT 40$: RETURN ;+ ; - THE MAGIC IS BACK!! - ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GSPKT ; ; R1 = IOP ADDRESS ; R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3 = KRB ADDRESS (UNLESS 0 THEN R3 = CONTROLLER INDEX). ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; UDA50 CLASS DISK I/O REQUEST PACKET FORMAT. ; ; WD 00 -- I/O QUEUE THREAD WORD (I.LINK). ; WD 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER (I.EFN & I.FLAG). ;DC412 ; WD 02 -- ADDRESS OF THE TCB OF THE REQUESTOR TASK (I.TCB). ;**-1 ; WD 03 -- POINTER TO SECOND LUN WORD IN REQUESTOR TASK HEADER (I.LN2). ; WD 04 -- CONTENTS OF THE FIRST LUN WORD IN REQUESTOR'S TASK HEADER ; (I.UCB). ; WD 05 -- I/O FUNCTION CODE (IO.RLB/IO.WLB) (I.FCN). ; WD 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK (I.IOSB). ; WD 07 -- RELOCATION BIAS OF I/O STATUS BLOCK (I.IOSB+2). ; WD 10 -- I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT + 140000) ; (I.IOSB+4). ; WD 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE (I.AST). ; ; FOLLOWING FORMAT APPLIES TO ALL DATA TRANSFER FUNCTIONS: ; ; WD 12 -- MEMORY EXTENSION BITS (BITS 4 AND 5) OF I/O TRANSFER (I.PRM). ; WD 13 -- BUFFER ADDRESS OF I/O TRANSFER (I.PRM+2). ; WD 14 -- NUMBER OF BYTES TO BE TRANSFERED (I.PRM+4). ; WD 15 -- DIAGNOSTIC SUPPLIMENTAL PARAMETER ELSE NOT USED (I.PRM+6). ; WD 16 -- HIGH PART OF LOGICAL BLOCK NUMBER AND HIGH BYTE NOT USED ; (I.PRM+10). ; WD 17 -- LOW PART OF LOGICAL BLOCK NUMBER OF I/O REQUEST (I.PRM+12). ; WD 20 -- RELOCATION BIAS OF DIAGNOSTIC REG. BLOCK ADRS ELSE NOT USED ; (I.PRM+14). ; WD 21 -- DIAGNOSTIC REG. BLOCK ADRS (REAL OR DISPLACEMENT + 140000) ; (I.PRM+16). ; ; SET CHARACTERISTICS FUNCTION CODE ; ; WD 12 -- ; WD 13 -- PARAMETER SPECIFICATION (I.PRM+2) ; 0 = RESET VOLUME VALID ; 1 = SET VOLUME VALID ; 2 = RESET VOLUME VALID, SPIN UNIT DOWN ; 3 = SET VOLUME VALID, SPIN UNIT UP ; -1 = SIZE UNIT (VOLUME VALID UNCHANGED) ; WD 14 -- ; ;- CMDRED: CLRB I.FLAG(R1) ; CLEAR INTERNAL FLAG BYTE ;DC412 MOV R1,R3 ; SAVE IOP ADDRESS ;**-1 .IF DF M$$PRO TST S.URM(R4) ; UNIBUS RUN MASK BEQ 37$ ; NONE, CONTINUE MOV @CPURM,-(SP) BIT S.URM(R4),@(SP)+ ; OK ON THIS CPU BNE 37$ ; YES. JUST EXIT ;+ ; GET FORK BLOCK AND QUEUE IT IN FORK LIST ; ; If the request is a control function, we cannot assume that the ; first descriptor in the IOP is a buffer, and if we allocate a fork ; block as a UMR wait block, then the first control parameter will ; be clobbered. So ... in this case, we will simply call $EXROP instead. ;- CMPB I.FCN+1(R1),#IO.STC/256. ; IS THIS A CONTROL FUNCTION? BNE 30$ ; NOPE, USE UMR WAIT BLOCK FOR $FORK MOV S.URM(R4),R2 ; GET THE TARGET URM MOV R3,R4 ; COPY THE IOP ADDRESS INTO R4 MOV #36$,R3 ; SET UP OUR SUBROUTINE ADDRESS CALLR @EXROP ; AND FORK TO THE TARGET CPU 30$: MOV (R2),R1 ; GET CST DEC C.UMCT(R1) ; DECREMENT THE UMR WAIT BLOCK COUNT ADD #C.UMRW,R1 ; POINT TO BEGINNING OF THE WAIT BLOCK MOV #-1,R2 ; COUNTER = -1 BECAUSE WE INCREMENT 32$: INC R2 ; INCREMENT THE INDEX COUNTER TST (R1) ; IS THERE A BLOCK HERE? BEQ 33$ ; IF EQ NO. ALLOCATE ANOTHER BIT #1,(R1)+ ; IS THE BLOCK IN USE? BNE 32$ ; YES. TRY ANOTHER MOV -(R1),R0 ; GET WAIT BLOCK BR 35$ ; GO TO COMMON CODE 33$: PUSH ; SAVE THE TABLE ADDRESS AND BLOCK INDEX MOV #UMRWTB,R1 ; SET LENGTH OF CORE BLOCK CALL @ALOCB ; GET A WAIT BLOCK POP ; RESTORE REGISTERS BCC 34$ ; WE GOT ONE,OK ; NO POOL, EXIT GRACEFULLY MOV S.QST(R4),R2 ; GET QST MOV (R2),R1 ; GET CST INC C.UMCT(R1) ; NOT GOING TO USE WAIT BLOCK AFTER ALL MOV #IE.NDR&377,R0 ; SET NO DYNAMIC MEMORY CLR R1 ; JMP @IOFIN ; COMPLETE I/O 34$: MOV S.URM(R4),(R0)+ ; PUT IN UNIBUS RUN MASK MOV R0,(R1) ; PUT THE NEW BLOCK ADDRESS IN THE TABLE 35$: INC (R1) ; SHOW THAT THE BLOCK IS IN USE MOVB R2,I.PRM(R3) ; SAVE UMR WAIT BLOCK INDEX IN IOP BISB #IP.UMR,I.FLAG(R3) ; MARK I/O AS HAVING A UMR WAIT BLOCK ;DC412 MOV R0,R4 ; PUT THE FORK BLOCK IN R4 ;**-1 CLR (R0)+ ; CLEAR THE FORK LINK MOV #36$,(R0)+ ; PUT IN RETURN ADDRESS MOV R5,(R0)+ ; R5, UCB ADDRESS MOV R3,(R0)+ ; IOP ADDRESS (COMES BACK IN R4) MOV @KISR5,(R0)+ ; APR 5 BIAS CALLR @QFORK ; QUEUE THE FORK BLOCK 36$: MOV R4,R3 ; RESTORE IOP ADDRESS MOV U.SCB(R5),R4 ; RECOVER R4 WHICH IS DESTROYED BY FORK MOV S.QST(R4),R2 ; RESTORE QST MOV S.PBIA(R4),@KISR6 ; MAP APR 6 TO PORT DRIVER MOV S.PBIA(R4),@#KINAR6 ; KERNAL INST SPACE MOV R3,R1 ; RESTORE THE IOP IN R1 FOR $VOLVD 37$: .ENDC ;M$$PRO .IF DF D$$DSK CMP #IO.SMD,I.FCN(R1) ; IS IT A SET MEDIA DENSITY FUNCTION? BNE 39$ ; NO. THEN CALL VOLVD BITB #US.UMD,U.ST2(R5) ; DEVICE ATTACHED FOR DIAGNOSTICS? BEQ 39$ ; NO. THEN CALL VOLVD BISB #US.VV,U.STS(R5) ; SET THE VV BIT FOR LATER CHECK 39$: CALL @VOLVD ; CHECK THE VOLUME VALID BCC 40$ ; IF IT WAS OK, CONTINUE CALLR ENDCM1 ; GO FINISH THE I/O 40$: .ENDC ;D$$DSK ; ; SCAN THE PRIMARY TABLE FOR THE I/O FUNCTION CODE. FOR TAPE, CONTROL WILL ; EITHER TRANSFER TO THE PROCESSING ROUTINE FOR THAT FUNCTION OR TO THE ; ROUTINE TO HANDLE ILLEGAL FUNCTIONS. FOR DISK, CONTROL WILL EITHER ; TRANSFER TO THE PROCESSING ROUTINE FOR THAT FUNCTION OR TO THE 'SCAN2' ; ROUTINE BELOW IN ORDER TO SCAN THE SECONDARY FUNCTION TABLE FOR A MATCH. ; MOV I.FCN(R3),R1 ; GET FUNCTION CODE BIC #IQ.Q!IQ.X!IQ.UMD,R1 ; CLEAR OUT ANY MODIFIERS MOV R1,EIOFUN ; INITIALIZE END OF TABLE MOV #IOFUN,R0 ; ADD OF I/O FUNCTION TABLE 50$: CMP R1,(R0) ; I/O CODES MATCH ? BEQ 60$ ; YES ADD #FOSIZ,R0 ; POINT TO NEXT FUNCTION CODE BR 50$ ; KEEP ON LOOKING 60$: JMP @FO.CMD(R0) ; DISPATCH TO FUNCTION SPECIFIC ROUTINE .PAGE .SBTTL CMDSTC - SET STATUS ;+ ; **-CMDSTC- ; ; THIS ROUTINE DISPATCHES ALL IO.STC COMMANDS. ONLINE AND GET UNIT STATUS ; COMMANDS ARE PASSED OFF TO OTHER ROUTINES. AVAILABLE COMMANDS ARE PROCESSED HERE ; ; FOR DISKM THE IO.STC FUNCTION WILL DO ONE OF THE FOLLOWING ACTIONS, DEPENDING ; ON THE VALUE IN I.PRM+2: ; ; I.PRM+2 Action ; ------- ------ ; 0 SET UNIT AS AVAILABLE ; 1 SET UNIT AS ONLINE ; 2 SET UNIT AVAILABLE, AND SPIN UNIT DOWN ; 3 SAME AS 1 ; -1 GET UNIT STATUS ; ; FOR TAPE, THIS ROUTINE PERFORMS THE SET CHARACTERISTIC FUNCTION. THIS ; MEANS THAT A TMSCP ONLINE COMMAND IS ISSUED, FOLLOWED BY A GET UNIT ; STATUS COMMAND. IF THE STC FUNCTION IS ISSUED BY CON/HRC, THE ONLINE ; COMMAND IS NOT ISSUED; THE GET UNIT STATUS COMMAND IS ISSUED. ; CON/HRC IS CONSIDERED TO HAVE SENT THE STC FUNCTION IF BOTH ARE TRUE: ; ; 1. UNIT IS ATTACHED FOR DIAGNOSTICS (US.UMD IS SET) ; 2. STC COMMAND HAS THE IQ.UMD SUBFUNCTION BIT SET ; ; INPUTS: ; ; R0 FUNCTION TABLE ENTRY ; R2 QST ADDRESS ; R3 IOP ADDRESS ; R4 SCB ADDRESS ; R5 UCB ADDRESS ; ; OUTPUTS: ; ;- CMDSTC: .IF DF D$$DSK TST I.PRM+2(R3) ; IS IT A GET UNIT STATUS? BGE 10$ ; NO. KEEP LOOKING CALLR CMDGUS ; GO DO IT THERE 10$: BIT #1,I.PRM+2(R3) ; IS IT AN ONL COMMAND? BEQ 20$ ; NO,CONTINUE CALLR CMDONL ; GO DO IT THERE 20$: CALL CMDCOM ; GO GET A COMMAND PACKET .IF DF,D$$DSK&D$$PRT ;DC412 BIT #UU.PRT,U.UTIL(R5) ; PARTITIONED DISK? ;DC412 BEQ 25$ ; NOPE, ALLOW THE SPIN DOWN ;DC412 ;DC412 MOV S.KRB(R4),R0 ; GET KRB ADDRESS ;DC412 ADD K.OFF(R0),R0 ; ADJUST TO UCB TABLE ;DC412 CLR -(SP) ; FORM AN ACCUMULATOR ;DC412 BISB U.UNIT(R5),(SP) ; GET UNIT NUMBER ;DC412 ASL (SP) ; *2 ;DC412 ADD (SP)+,R0 ; POINT TO MASTER UNIT ;DC412 MOV (R0),R0 ; MASTER UNIT UCB ;DC412 BIT #UU.PTV,U.UTIL(R0) ; PARTITION TABLE VALID? ;DC412 BEQ 25$ ; IF EQ, NOPE, ALLOW SPIN DOWN ;DC412 MOV U.UC2X(R0),@KISR6 ; MAP TO THE UCBX ;DC412 DECB 140000+X.PONL ; DROP NUMBER OF ONLINE PARTITIONS ;DC412 BNE 30$ ; IF NE, WE WON'T SPIN DOWN ;DC412 25$: ; REFERENCE LABEL ;DC412 .IFTF ;DF,D$$DSK&D$$PRT ;DC412 TST I.PRM+2(R3) ; SHOULD WE SPIN IT DOWN TOO? BEQ 30$ ; NO,KEEP GOING MOV U.UC2X(R5),@KISR6 ; MAP SECOND UCB EXTENSION MOV X.UNFL+140000,R0 ; RETRIEVE UNIT FLAGS .IFF ;DF,D$$DSK&D$$PRT ;DC412 MOV S.PBIA(R4),@KISR6 ; RESTORE PORT MAPPING ;DC412 .IFTF ;DF,D$$DSK&D$$PRT ;DC412 BIT #UF.RMV,R0 ; IS THE DISK REMOVABLE? ;**-1 BEQ 30$ ; NO. DON'T SPIN DOWN FIXED DISKS MOV #MD.SPD,P.MOD(R1) ; SET SPIN DOWN MODIFIER 30$: .IFT ;DF,D$$DSK&D$$PRT ;DC412 MOV S.PBIA(R4),@KISR6 ; RESTORE PORT MAPPING ;DC412 .ENDC ;DF,D$$DSK&D$$PRT ;DC412 PUSH <#CLACMD> ; RETURN TO STARTING OTHER COMMANDS ;DC412 CALL CMDSEN ;**-1 ; ; RETURN TO THIS POINT WITH END PACKET ; REGISTERS ARE THE SAME EXCEPT THAT R1 CONTAINS AN END PACKET INSTEAD OF A ; COMMAND PACKET. ; CALL ENDERR ; CHANGE END CODE TO RSX STATUS CODE PUSH <#0> ; NO BYTE COUNT CMP #ST.SDI!ST.CON,P.STS(R1); WAS SPIN DOWN IGNORED? BNE 70$ ; NO. JUST FINISH UP ; ; WE HAVE TO SPIN DOWN THE OTHER UNIT ; CALL ENDCMO ; GO FINISH THE COMMAND, AND COME BACK MOV U.UC2X(R5),@KISR6 ; MAP SECOND UCB EXTENSION MOV X.MLUN+140000,R2 ; GET MULTI-UNIT CODE MOV S.PBIA(R4),@KISR6 ; RESTORE PORT MAPPING MOV R5,R0 ; SAVE THE ORIGINAL UCB IN R0 PUSH <#SCUCB> ; NOW SEARCH TO FIND ONE THAT MATCES 40$: CALL @(SP)+ ; GET A UCB BCC 50$ ; WE GOT ONE, CHECK IT OUT MOV S.QST(R4),R2 ; RESTORE THE QST BEFORE EXITING RETURN ; END OF UCB SEARCH, EXIT 50$: CMP R0,R5 ; IS IT THE UCB WE STARTED WITH? BEQ 40$ ; YES. GET NEXT ONE MOV U.UC2X(R5),@KISR6 ; MAP SECOND UCB EXTENSION MOV X.MLUN+140000,R1 ; GET MULTI-UNIT CODE MOV S.PBIA(R4),@KISR6 ; RESTORE PORT MAPPING CMP R1,R2 ; MULTI UNIT CODE THE SAME? BNE 40$ ; NO. GET ANOTHER ONE ADD #10,SP ; WE FOUND IT, FLUSH THE UCB SCAN BIS #UU.IOS,U.UTIL(R5) ; SET THE STALL I/O BIT MOV #T.NIOS,R0 ; I/O STALLED CONSOLE MESSAGE CALL @DVMSG ; GO PRINT IT MOV S.QST(R4),R2 ; GET QST MOV (R2),R3 ; /*Q.CST*/ AND THE CST CALL PIOPAL ; ALLOCATE A PIOP MOV #AVNFUN,R0 ; SET UP THE AVAILABLE FUNCTION TABLE CALL CMDCOM ; GO GET A PACKET MOV #MD.SPD,P.MOD(R1) ; SET THE SPIN DOWN MODIFIER PUSH <#CLACMD> ; SEE IF WE CAN START MORE COMMANDS CALL CMDSEN ; SEND OFF THE PACKET ; ; END PACKET RETURNS HERE. WE CAN'T REALLY DO ANYTHING INTELLIGENT IF THE I/O ; IS NOT A SUCCESS, SO JUST COMPLETE IT. ; PUSH <#0> ; NO BYTE COUNT MOV #IS.SUC&377,R0 ; SHOW SUCCESSFUL 70$: JMP ENDCOM ; FINISH IT .IFF ;D$$DSK BIT #IQ.UMD,I.FCN(R3) ; USER MODE DIAGNOSTIC BIT SET? BEQ 20$ ; NO. DO ONLINE/GET-UNIT-STATUS BITB #US.UMD,U.ST2(R5) ; ATTACHED FOR DIAGNOSTICS? BEQ 20$ ; NO. DO ONLINE/GET-UNIT-STATUS MOV #GUSFUN,R0 ; ISSUE A GET-UNIT-STATUS COMMAND CALL CMDCOM ; BUILD THE COMMAND PACKET NEEDED PUSH <#CLACMD> ; WHENCE TO RETURN CALL CMDSEN ; ISSUE THE COMMAND ; ; END PACKET PROCESSING ; MOV P.STS(R1),R0 ; GET STATUS CODE BIC #^C,R0 ; GET MAJOR STATUS CODE CMP R0,#ST.AVL ; IS IT AVAILABLE CODE? BNE 10$ ; NO. CLR R0 ; /*ST.SUC*/ ; INDICATE SUCCESS ANYWAY 10$: CALL ENDERR ; CONVERT TO RSX STATUS CODE PUSH <#0> ; NO STATUS FOR IOSB + 2 CALLR ENDCOM ; AND GO CLEAN UP PROPERLY 20$: BIT #M.BOT,U.CW2(R5) ; ARE WE AT BOT? BEQ 25$ ; NO. DO NOT WORRY ABOUT IT BIT #UU.BLK,U.UTIL(R5) ; DOES UNIT SUPPORT MULTIPLE DENSITIES? BNE 25$ ; NO. NOTHING TO DO IN HERE PUSH ; SAVE ORIG IOP ADDR CALL PIOPAL ; GET A PIOP FOR THE COMMAND POP ; SAVE ORIG IOP ADDR IN PIOP MOV #AVNFUN,R0 ; FUNCTION CODE ENTRY TO USE CALL CMDCOM ; BUILD TEMPLATE COMMAND BIS #MD.CSE,P.MOD(R1) ; SET 'CLEAR SERIOUS EXCEPTION' MOD PUSH <#CLACMD> ; WHERE TO RETURN TO CALL CMDSEN ; ISSUE THE COMMAND PUSH ; SAVE REGISTERS FOR LATER PUSH ; SAVE ORIG IOP ADDR MOV #IS.SUC,R0 ; NON-ZERO -> RETURN PACKET TO POOL PUSH <#0> ; NO IOSB DATA EITHER CALL ENDCMO ; CLEAN UP PACKET USED POP ; RESTORE ORIG PIOP ADDR POP ; RESTORE REGISTERS 25$: CALLR CMDONL ; ISSUE ONLINE/GET-UNIT-STATUS .ENDC ;D$$DSK .PAGE .IF DF,D$$DSK .SBTTL CMDTRM - PROCESS RCT TERMINATION ;+ ; **-CMDTRM- PROCESS RCT TERMINATION REQUESTS ; ; THIS SECTION DOES ALL THE PROCESSING SPECIFIC TO TERMINATION REQUESTS. ; I.PRM CONTAINS THE ADDRESS OF THE I/O THAT MUST BE RESTARTED, AND I.PRM+2 ; CONTAINS THE STATUS CODE RETURNED FROM RCT. ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ;- CMDTRM: BIT #IQ.X!IQ.Q!IQ.UMD,I.FCN(R3) ; THESE MODIFIERS ARE ILLEGAL BEQ 10$ ; IT'S OK CALLR ILEGAL 10$: MOV R5,R0 ; COPY THE UCB TO R0 ADD #U.BPKT,R0 ; ADD THE OFFSET TO THE BAD BLOCK QUEUE MOV I.PRM(R3),R1 ; GET I/O THAT INITIATED THE REPLACE BEQ 40$ ; IF NO IOP THEN JUST COMPLETE WITH SUCCE PUSH ; SAVE R3 CALL @QRMVA ; REMOVE IT FROM THE QUEUE MOV (SP),R3 ; GET R3, BUT LEAVE IT ON THE STACK CMPB #IS.SUC,I.PRM+2(R3) ; DID RCT SUCCEED? BNE 20$ ; NO. COMPLETE THE I/O .IF DF D$$PRT!E$$LBN ;DC412 MOV I.TCB(R1),R0 ; GET THE TCB ADDRESS ;DC412 MOVB T.PRI(R0),I.PRI(R1) ; RESTORE PRIORITY FOR REQUEUE ;DC412 .ENDC ;DF,D$$PRT!E$$LBN ;DC412 MOV R4,R0 ; COPY THE SCB TO R0 (S.LHD IS AT 0) CALL @QINSP ; INSERT THE IOP BACK IN THE SCB QUEUE MOV S.QST(R4),R2 ; RESTORE R2 BR 30$ ; COMMON END POINT 20$: MOV S.QST(R4),R2 ; RESTORE R2 MOV I.PRM+2(R3),R0 ; GET STATUS CODE MOV I.PRM(R3),R3 ; MOVE THE ORIGINAL IOP TO R3 CLR R1 ; NO BYTE COUNT CALL ENDCM1 ; FINISH THE I/O 30$: POP ; RESTORE R3 40$: MOV #IS.SUC&377,R0 ; SUCCESS STATUS CLR R1 ; NO BYTE COUNT PUSH <#CLACMD> ; TRY TO START MORE I/O CALLR ENDCM1 ; FINISH THE I.TRM .ENDC ;D$$DSK .PAGE .SBTTL ENDCOM - COMMON PROCESSING TO COMPLETE AN I/O REQUEST ;+ ; **-ENDCOM - COMMON PROCESSING TO COMPLETE AN I/O REQUEST ; **-ENDCMO - ALTERNATE ENTRY POINT FOR ENDCOM (RETURN TO CALLER) ; ROUTINE DESCRIPTION ; ; INPUTS: ; ; R0 = STATUS (0 -> DO NOT CALL $IOFIN, I/O STILL PENDING) ; R1 = END PACKET ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; (SP)=BYTECOUNT ; ; OUTPUTS: (FALLING THROUGH TO ENDCM1) ; ; R0,R2-R5 ARE PRESERVED ; R1 IS SET TO BYTECOUNT ;- ENDCMO: MOV (SP),-(SP) ; COPY TOP OF STACK TO A TEMPORY CELL MOV 4(SP),2(SP) ; GET SPACE FOR SECOND VALUE MOV (SP)+,2(SP) ; FINISH THE EXCHANGE ENDCOM: .IF DF E$$LOG TST R0 ; IS THERE ENDING STATUS BEQ 10$ ; NO. THEN WE DON'T LOG THE PACKET CMP #ST.VOL,P.STS(R1) ; IS IT 'NO VOLUME MOUNTED'? BEQ 10$ ; YES. DO NOT LOG IT FOR TAPE BITB #EF.LOG,P.STS(R1) ; IS THERE AN ERRORLOG PACKET TO FOLLOW BEQ 10$ ; NO. THEN DON'T LOG .IF DF,D$$DSK BIT #UU.SEL,U.UTIL(R5) ; LOG PACKET FOR THIS DEVICE? BNE 10$ ; NE - DO NOT LOG THE PACKET .ENDC ;D$$DSK CMPB #OP.ONL!OP.END,P.OPCD(R1); ONLINE COMMAND? BEQ 10$ ; DO NOT LOG PACKET .IF DF,T$$APE CMPB #OP.AVL!OP.END,P.OPCD(R1); AVAILABLE COMMAND? BEQ 10$ ; DO NOT LOG PACKET .ENDC ;T$$APE CALL LERR ; LOG THE ERROR 10$: .ENDC ;E$$LOG BIT #IQ.UMD,I.FCN(R3) ; USER MODE DIAGNOSTIC REQUEST? BEQ 70$ ; NO PUSH ; SAVE WORK REGISTERS MOV R3,R0 ; COPY OF IOP ADDRESS .IF DF T$$APE CMPB #IO.EOF/256.,I.FCN+1(R3); WRITE EOF FUNCTION BEQ 20$ ; IF EQ YES CMPB #IO.RWD/256.,I.FCN+1(R3); REWIND FUNCTION BNE 30$ ; IF EQ YES 20$: MOV I.PRM+14(R3),I.PRM+16(R3); RELOCATE BIAS MOV I.PRM+12(R3),I.PRM+14(R3); RELOCATE ADDRESS 30$: .IFTF ;T$$APE MOV I.PRM+14(R0),R3 ; DESTINATION APR 6 BIAS BEQ 40$ ; NO BUFFER MOV I.PRM+16(R0),R4 ; REGISTER BUFFER ADDRESS BEQ 40$ ; NO BUFFER MOV R1,R2 ; R2 IS THE SOURCE DISP SUB #ENVLEN,R2 ; BACK TO START OF HEADER BIC #160000,R2 ; R2 IS ADDRESS IN APR 5 RANGE BIS #120000,R2 ; MOV @KISR6,R1 ; R1 IS SOURCE APR 5 BIAS MOV #RPLEN+ENVLEN,R0 ; NUMBER OF BYTES CALL @BLXIO ; MOVE THE DATA 40$: .IFT ;T$$APE MOV 2(SP),R3 ; RESTORE IOSB ADDRESS CMPB #IO.EOF/256.,I.FCN+1(R3); WRITE EOF FUNCTION BEQ 50$ ; IF EQ YES CMPB #IO.RWD/256.,I.FCN+1(R3); REWIND FUNCTION BNE 60$ ; IF EQ YES 50$: MOV I.PRM+14(R3),I.PRM+12(R3); RESTORE BIAS MOV I.PRM+16(R3),I.PRM+14(R3); RESTORE ADDRESS 60$: .ENDC ;T$$APE POP ; RESTORE ORIGINAL CONTENTS 70$: PUSH ; SAVE COMPLETION CODE/IOP ADDRESS CALLV PORT,PKTDR ; DEALLOCATE END PACKET MOV R3,R1 ; SAVE THE PACKET ADDRESS MOV (R2),R0 ; GET CST ADD #C.OLHD,R0 ; POINT TO QUEUE HEAD CMP R1,(R0) ; IS THIS THE OLDEST PACKET IN THE QUEUE BNE 90$ ; NO. DON'T BOTHER WITH TIMER ; ; MUST TAKE CARE OF TIMER BECAUSE OLDEST COMMAND IS DONE ; TST (R1) ; OTHER PACKETS ON QUEUE BEQ 80$ ; NO. THEN DON'T RESTART TIMER ; ; RESET TIMEOUT COUNT FOR NEW OLDEST COMMAND AND RESET BUSY UCB ; MOV (R1),R1 ; ADDRESS OF THE NEW OLDEST CMD MOV I.UCB(R1),R1 ; UCB OF THE NEW OLDEST BICB #US.BSY,U.STS(R5) ; CLEAR OLD BUSY UNIT BISB #US.BSY,U.STS(R1) ; SET NEW BUSY UNIT MOV R1,S.BSYU(R4) ; REMEMBER NEW BUSY UNIT MOVB S.ITM(R4),S.CTM(R4) ; SET TIMER MOV (R0),R1 ; GET BACK THE IOP WE'RE WORKING ON BR 90$ ; ; STOP THE TIMER THERE ARE NO MORE COMMANDS OUTSTANDING ; 80$: CLRB S.CTM(R4) ; STOP TIMER BICB #US.BSY,U.STS(R5) CLR S.BSYU(R4) ; CLEAR BSYUCB 90$: CALL @QRMVA ; REMOVE THE PACKET FROM THE QUEUE MOV S.QST(R4),R2 ; RESTORE QST ADDRESS POP ; GET IOP ADDR, COMPL CODE, BYTE COUNT ; ; FALL THROUGH TO ENDCM1 ; .PAGE .SBTTL ENDCM1 - ALTERNATE ENTRY POINT FOR COMMANDS WITHOUT AN END PACKET ;+ ; **-ENDCM1 - ALTERNATE ENTRY POINT FOR COMMANDS WITHOUT AN END PACKET ; ROUTINE DESCRIPTION ; ; INPUTS: ; ; R0 = STATUS (0 -> DO NOT CALL $IOFIN, I/O STILL PENDING) ; R1 = BYTECOUNT ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0-R1 DESTROYED ; R2,R4-R5 ARE PRESERVED ; R3 IS SET TO CST ;- ENDCM1: ; ; DEALLOCATE UMRS IF THEY WERE ALLOCATED ; BITB #IP.UMR,I.FLAG(R3) ; UMR WAIT BLOCK ALLOCATED FOR THIS? ;DC412 BEQ 20$ ; IF EQ NO ;DC412 PUSH ; SAVE R2 AND R3 ;DC412 BICB #IP.UMR,I.FLAG(R3) ; CLEAR THE UMR FLAG ;DC412 MOV (R2),R2 ; GET CST ;**-4 BIS #C1.DQU,(R2) ; SET THE BIT TO CALL $DQUMR ADD #C.UMRW,R2 ; POINT TO BEGINNING OF THE WAIT BLOCK MOVB I.PRM(R3),R3 ; GET BLOCK INDEX PUSH ; SAVE THE BLOCK INDEX ASL R3 ; MAKE THE INDEX A WORD OFFSET ADD R3,R2 ; ADD IT TO THE BEGINNING OF THE TABLE DEC (R2) ; CLEAR THE IN USE BIT PUSH ; SAVE THE TABLE ADDRESS MOV (R2),R2 ; GET ADDRESS OF THE BLOCK FOR DEUMR ADD #10,R2 ; POINT TO THE MAPPING INFO MOV S.QST(R4),R3 ; GET QST MOV (R3),R3 ; NOW THE CST INC C.UMCT(R3) ; INCREMENT UMR ASSIGNMENT BLOCK COUNT CALL @DEUMR ; DEASSIGN THE UMRS POP ; RESTORE BLOCK INDEX AND BLOCK ADDRESS .IIF DF D$$DSK CMP #DUUMR,R3 ; DYNAMICALLY ALLOCATED BLOCK? .IIF DF T$$APE CMP #MUUMR,R3 ; DYNAMICALLY ALLOCATED BLOCK? BGE 10$ ; IF GE, NO PUSH ; SAVE R0 AND R1 MOV (R2),R0 ; MOV THE ADDRESS FOR $DEACB .IIF DF M$$PRO TST -(R0) ; ADJUST FOR EXTRA WORD FOR URM CLR (R2) ; CLEAR THE ADDRESS IN THE TABLE MOV #UMRWTB.,R1 ; LENGTH OF THE BLOCK CALL @DEACB ; DEALLOCATE THE WAIT BLOCK POP ; RESTORE R1 AND R0 10$: POP ; RESTORE R3 AND R2 20$: TST R0 ; DO WE COMPLETE THIS IO BEQ 40$ ; NO. THEN WE EXIT BITB #IP.FAK,I.FLAG(R3) ; IS IT A PIOP ;DC412 BEQ 30$ ; NO. FINISH THE I/O ;**-1 MOV R3,R1 ; ADDRESS OF PIOP TO DEALLOCATE MOV (R2),R3 ; WE NEED CST FOR PIOPDE CALLR PIOPDE ; DEALLOCATE THE PIOP 30$: PUSH CALL @IODSA ; SPECIAL ENTRY POINT FOR MSCP DEVICES POP MOV U.SCB(R5),R4 ; RECOVER R4 (DESTROYED BY $IOFIN) MOV S.PBIA(R4),@KISR6 ; MAP APR 6 TO PORT DRIVER ;DC513 MOV S.PBIA(R4),@#KINAR6 ; FOR I/D SYSTEMS MAP BOTH I AND D ;DC513 MOV S.QST(R4),R2 ; RESTORE QST ADDRESS 40$: MOV (R2),R3 ; CST IS RESTORED RETURN .PAGE .SBTTL ENDERR - TRANSLATE MSCP ERROR CODE TO RSX CODE ;+ ; **-ENDERR- TRANSLATE MSCP ERROR CODE TO RSX CODE ; ; THIS ROUTINE LOOKS AT THE CURRENT END PACKET, POINTED TO BY R1, AND ; TRANSLATES THE MSCP ERROR RETURNED TO THE RSX EQUIVALENT. IN SOME ; ERRORS, ADDITIONAL ACTION IS REQUIRED, E.G. FOR POSITION LOST ERRORS, ; THE POWER FAIL BIT MUST BE SET. ; ; INPUTS: ; ; R1 = END PACKET ADDRESS ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0 = RSX ERROR STATUS (CAN BE IS.SUC AS WELL) ; R1-R5 = PRESERVED ; POWERFAIL FLAG SET IF TMSCP ERROR IS ST.POL(POSITION LOST) ; ;- ENDERR: .IF DF T$$APE BITB #EF.EOT,P.FLGS(R1) ; WAS PHYSICAL EOT REACHED? BEQ 10$ ; NO. MOVB P.OPCD(R1),R0 ; GET US THE ACTUAL OPCODE USED BIC #177400!OP.END,R0 ; CLEAR ALL BUT THE OPCODE ITSELF CMP R0,#OP.RD ; WAS THIS EITHER READ FUNCTION? BEQ 10$ ; YES. DON'T REPORT EOT ON SUCH THINGS CMP R0,#OP.REP ; IS THIS A SPACING FUNCTION? BEQ 10$ ; YES. KEEP ORIGINAL STATUS CODE CMP R0,#OP.CMP ; IS THIS A COMPARE HOST DATA? BEQ 10$ ; YES. KEEP ORIGINAL STATUS CODE MOV #IE.EOT&377,R0 ; INDICATE PHYSICAL END OF TAPE BIC #M.AEOV!M.BOT!M.RWD!M.SER!M.TMK,U.CW2(R5) ; NEW STATES BIS #M.EOT,U.CW2(R5) ; NEW STATE RETURN ; THAT'S ALL WE NEED FOR THIS ONE 10$: .IFTF ;T$$APE PUSH ; SAVE. NEED AS A WORK REGISTER MOV P.STS(R1),R1 ; GET TMSCP STATUS CODES BIC #^C,R1 ; CLEAR OUT THE SUBCODE .IFT ;T$$APE CMP #ST.AVL,R1 ; IS THE UNIT AVAILABLE? BEQ 20$ ; YES. THIS MEANS CERTAIN STATE CMP #ST.BOT,R1 ; IS THERE A BOT INDICATION? BNE 30$ ; NO. 20$: BIS #M.BOT,U.CW2(R5) ; INDICATE AT BOT BIC #M.AEOV!M.PEOV!M.RWD!M.SER!M.TMK!M.EOT,U.CW2(R5) ; NEW STATES 30$: .IFTF ;T$$APE MOVB RSXTAB(R1),R0 ; TRANSLATE THE ERROR CODE BIC #177400,R0 ; CLEAR OUT THE HIGH BYTE OF STATUS .IFT ;T$$APE CMPB R1,#ST.POL ; POSITION LOST ERROR? BNE 40$ ; NO. GO CLEAN UP BISB #US.PWF,U.STS(R5) ; SET POWERFAIL BIT FOR UNIT 40$: POP ; RESTORE END PACKET ADDRESS .IFF POP ; RESTORE END PACKET ADDRESS CMP P.STS(R1),#ST.DAT ; IS IT FORCED ERROR? BNE 50$ ; NO. LEAVE IT ALONE MOV #IE.FER&377,R0 ; SET FORCED ERROR STATUS CODE 50$: .ENDC CMP #ST.OFL,P.STS(R1) ; WAS IT UNIT OFFLINE? BNE 60$ ; NO. JUST EXIT MOV #IE.IDU&377,R0 ; ST.OFL MEANS NO SUCH UNIT 60$: RETURN .PAGE .IF DF,D$$DSK .SBTTL ENDSIO - TRY TO STALL I/O ;+ ; **-ENDSIO- TRY TO STALL I/O ; ; INPUTS: ; ; R1 END PACKET ADDRESS ; R2 QST ADDRESS ; R3 (P)IOP ADDRESS ; R4 SCB ADDRESS ; R5 UCB ADDRESS ; ; OUTPUTS: ; CARRY CLEAR - R1-R5 PRESERVED, I/O NOT STALLED ; CARRY SET - R2,R4,R5 PRESERVED, I/O STALLED ;- ENDSIO: MOV P.STS(R1),R0 ; GET STATUS WORD BIC #^C,R0 ; CLEAR SUBSTATUS BITS CMP #ST.OFL,R0 ; OFFLINE TO DISK BEQ 5$ ; YES. SHOULD TRY TO STALL I/O CMP #ST.AVL,R0 ; HOW ABOUT AVL STATE? BNE 20$ ; NOT THAT EITHER, CONTINUE 5$: BITB #IP.FAK,I.FLAG(R3) ; IS IT A PIOP? ;DC412 BNE 20$ ; YES. LET PIOP'S THROUGH FOR RECOVERY ;**-1 BIT #UU.SIO,U.UTIL(R5) ; DOES THIS UNIT STALL I/O? BEQ 20$ ; IF EQ NO BITB #US.MNT,U.STS(R5) ; IS THE UNIT MOUNTED? BNE 20$ ; NO. DON'T STALL I/O CLR R0 ; INDICATE NOT TO FINISH I/O PUSH ; SAVE THE IOP AND SHOW NO BYTE COUNT CALL ENDCMO ; CLEAN UP THE END PACKET POP ; GET IOP .IF DF D$$DSK&DU$CHK ; IF QUEUE OPTIMIZATION MOV I.UCB(R1),R5 ; MAKE SURE WE HAVE THE RIGHT UCB CALL REQUE ; RECONVERT THE LBN .ENDC ;D$$DSK&DU$CHK MOV R4,R0 ; MOVE THE S.LHD QUEUE TO R0 FOR $QINSB CALL @QINSB ; INSERT AT THE BEGINNING OF THE QUEUE BIT #UU.IOS,U.UTIL(R5) ; DID WE ALREADY STALL I/O? BNE 10$ ; YES. DON'T REISSUE THE MESSAGE BIS #UU.IOS,U.UTIL(R5) ; SET THE STALL I/O BIT MOV #T.NIOS,R0 ; SET I/O STALLED MESSAGE CALL @DVMSG ; GO SEND IT MOV S.QST(R4),R2 ; RESTORE R2 10$: SEC ; SHOW THAT WE STALLED IT RETURN 20$: CLC ; WE DIDN'T STALL IT RETURN .ENDC ;D$$DSK .PAGE .SBTTL FINIO - FINISH UP ALL I/O IN A QUEUE ;+ ; **-FINIO-FINISH ALL I/O IN A QUEUE AS IE.FHE ; ; INPUTS: ; ; R1 INITIAL POINTER FOR QUEUE ; R2 QST ADDRESS ; R4 SCB ADDRESS ; R5 UCB ADDRESS ; ; OUTPUTS: ; R2,R4,R5 PRESERVED ;- FINIO: MOV R1,R3 ; COPY THE QUEUE ADDRESS TO R3 MOV (R3),R3 ; GET FIRST PACKET BEQ 20$ ; THERE AREN'T ANY, SO JUST LEAVE CLR (R1) ; REINITIALIZE THE QUEUE MOV R1,2(R1) ; ... 10$: MOV #IE.FHE&377,R0 ; FATAL HARDWARE ERROR CLR R1 ; NO BYTE COUNT PUSH <(R3)> ; SAVE LINK TO NEXT IOP IN THE QUEUE CALL ENDCM1 ; GO FINISH IT POP ; GET LINK TO NEXT IOP IN THE QUEUE BNE 10$ ; GO DO THE NEXT ONE 20$: RETURN .PAGE .SBTTL GCSSIO - INITIATE A GET COMMAND STATUS ;+ ; **-GCSSIO-INITIATE A GET COMMAND STATUS COMMAND (OP.GCS) ; ; INPUTS: ; ; R2 QST ADDRESS ; R3 CST ADDRESS ; R4 SCB ADDRESS ; R5 UCB ADDRESS ; ; OUTPUTS: ; ;- GCSSIO: TST C.OLHD(R3) ; I/O STILL THERE? BNE 10$ ; IF NE, YES. CHECK ON IT BIC #C1.GCS,(R3) ; FORGET ABOUT ISSUING OP.GCS JMP CLACMD ; GO TRY TO START SOMETHING ; ; ISSUE 'GET COMMAND STATUS' COMMAND FOR OLDEST COMMAND ; 10$: BIS #C1.TMO,(R3) ; WE'RE NOW IN TIMEOUT STATE BIC #C1.GCS,(R3) ; SHOW THAT WE DID THE GCS MOV #GCSFUN,R0 ; GET GCS FUNCTION TABLE MOVB FO.SZ(R0),R0 ; GET SIZE OF THE PACKET CALLV PORT,PKTAC ; GET A PACKET MOV C.OLHD(R3),R0 ; GET ADDRESS OF THE OLDEST COMMAND MOV #OP.GCS,P.OPCD(R1) ; SET UP GCS OP CODE MOVB I.FLAG(R0),P.OTRF(R1) ; OUTSTANDING REFERENCE NUMBER ;DC412 BIC #^C<17>,P.OTRF(R1) ; CLEAR OUT ALL BUT THE SEQUENCE BITS ;**-1 MOV R0,P.OTRF+2(R1) ; IOP ADDRESS IS THE SECOND CRF NUMBER MOV R0,P.CRF(R1) ; USE THE IOP FOR BOTH OF THE CRF NUMBERS MOV R0,P.CRF+2(R1) ; ... MOV I.UCB(R0),R5 ; GET CORRECT UCB ADDRESS BISB U.UNIT(R5),P.UNIT(R1) ; UNIT NUMBER (WAS ZEROED IN PKTAC) CALLV PORT,PORSEN ; SEND THE COMMAND JMP CLACMD ; GO TRY TO START OTHER COMMANDS .PAGE .SBTTL GUSSIO - START AND PROCESS AN OP.GUS REQUEST .SBTTL CMDGUS - GET UNIT STATUS ;+ ; **-GUSSIO - START AND PROCESS AN OP.GUS REQUEST ; ; THIS ROUTINE ISSUES GUS COMMANDS. THE GUSSIO ENTRY POINT WILL ISSUE A ; FOR ANY UNIT THAT HAS UU.GUS SET. ; ; INPUTS: ; ; ASSUMES ONE SCB PER CONTROLLER ; R2 = QST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; IF C1.GUS IS CLEARED THEN ; ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; **-CMDGUS - GET UNIT STATUS ; ; ROUTINE DESCRIPTION ; ; CONTROL IS PASSED TO THIS POINT WHEN A GET UNIT STATUS COMMAND IS ISSUED BY ; THE USER, SUCH AS IN AN IO.STC COMMAND ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2-R5 ARE PRESERVED ; ;- .ENABL LSB CMDGUS: PUSH <#CLACMD> ; RETURN TO CLASS COMMAND BR 30$ ; GO TO COMMON CODE GUSSIO: ; ; LOOK FOR UNITS NEEDING OP.GUS'S ; PUSH <#SCUCB> ; START A UCB SCAN 10$: CALL @(SP)+ ; GO GET A UCB BCC 20$ ; WE GOT ONE JMP 190$ ; NONE LEFT, EXIT 20$: BIT #UU.GUS,U.UTIL(R5) ; IS AN OP.GUS REQUIRED? BEQ 10$ ; IF EQ, NO. TRY NEXT ONE BIC #UU.GUS,U.UTIL(R5) ; LEAVE UU.GUS STATE BIS #UU.SER,U.UTIL(R5) ; MAKE SURE WE'RE IN SERIAL MODE CALL PIOPAL ; GO GET A PIOP PUSH <#200$> ; RETURN TO ISSUING MORE GUS COMMANDS 30$: MOV #GUSFUN,R0 ; R0 POINTS TO TABLE ENTRY FOR OP.GUS CALL CMDCOM ; SET UP COMMAND PACKET CALL CMDSEN ; SEND THE COMMAND TO THE CONTROLLER ; ; PROCESS END PACKET FOR OP.GUS - INPUTS: ; ; R1 = END PACKET ADDRESS ; R3 = IOP ADDRESS ; R2 = QST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; .IF DF D$$DSK ; ; SAVE INFORMATION IN UCB EXTENSION ; PUSH ; SAVE END PACKET, QST, IOP MOV #,R0 ; SET NUMBER OF BYTES TO MOVE MOV R1,R2 ; COPY MSCP PACKET POINTER TO R2 ADD #P.MLUN,R2 ; UPDATE OFFSET INTO MSCP PACKET MOV @KISR6,R1 ; GET PACKET'S BASE ADDRESS SUB #20000,R2 ; BIAS IT PROPERLY MOV U.UC2X(R5),R3 ; GET DESTINATION APR6 BIAS MOV #X.MLUN+140000,R4 ; GET DESTINATION DISPLACEMENT CALL @BLXIO ; MOVE THE DATA MOV U.SCB(R5),R4 ; RESTORE THE SCB ADDRESS .IF DF D$$DSK&DU$CHK ; IF QUEUE OPTOMIZATION SUPPORTED MOV 4(SP),R2 ; RETRIEVE MSCP PACKET POINTER MOVB P.TRCK(R2),U.PRM(R5) ; SET UP SECTORS/TRACK MOVB P.GRP(R2),R0 ; GET TRACKS/GROUP MUL P.CYL(R2),R0 ; MULTIPLY BY GROUPS/CYLINDER MOVB R1,U.PRM+1(R5) ; SET UP TRACKS/CYLINDER MOV R1,R0 ; SET UP FOR MULTIPLY MUL P.TRCK(R2),R0 ; COMPUTE SECTORS/CYLINDER MOV U.CW3(R5),R3 ; SET UP MAX LBN ... MOVB U.CW2(R5),R2 ; ... DIV R1,R2 ; COMPUTE CYLINDERS/UNIT MOV R2,U.PRM+2(R5) ; SET UP CYLINDERS/UNIT .ENDC ;D$$DSK&DU$CHK ; ; THE NEXT SECTION OF CODE SETS MULTI-UNIT CODES FOR THE UNIT. IF THE MULTI- ; UNIT CODE OF THIS UNIT MATCHES THAT OF ANY OTHER UNITS ON THE CONTROLLER, UU.S ; IS SET IN THE UCB OF THE FIXED DISK. THIS INDICATES THAT I/O CAN BE STALLED ; TO THIS UNIT. FOR M-PLUS, US.MUN IS SET IN THE UCB OF THE REMOVABLE DISK. ; THIS TELLS DISMOUNT TO ISSUE WARNING MESSAGES ABOUT MULTI-UNIT SPIN DOWN AND ; TO PREVENT NON-PRIVILEGED USERS FROM SPINNING DOWN THE DISK ; MOV 4(SP),R1 ; GET END PACKET BACK MOV P.UNFL(R1),R0 ; GET UNIT FLAGS MOV P.MLUN(R1),R2 ; AND THE MULTI-UNIT CODE BEQ 90$ ; IF NO CODE, UNIT IS OFFLINE MOV R5,R3 ; SAVE THE UCB PUSH <#SCUCB> ; GET UCB SEARCH ADDRESS 50$: CALL @(SP)+ ; GO GET A UCB BCS 90$ ; ALL DONE CMP R5,R3 ; IS IT THE SAME UCB? BEQ 50$ ; YES. GO GET ANOTHER PUSH <@KISR6> ; SAVE THE PORT MAPPING MOV U.UC2X(R5),@KISR6 ; MAP THE SECOND EXTENSION MOV 140000+X.UNFL,R1 ; GET UNIT FLAGS MOV 140000+X.MLUN,R4 ; AND THE MULTI-UNIT CODE POP <@KISR6> ; REMAP THE PORT CMP R2,R4 ; ARE THE MULTI-UNIT CODES THE SAME? BNE 50$ ; NO. GO TRY ANOTHER BIT #UF.RMV,R0 ; IS THE ORIGINAL REMOVABLE? BNE 60$ ; IF NE YES BIS #UU.SIO,U.UTIL(R3) ; INDICATE DEVICE CAN STALL I/O BICB #US.MUN,U.ST2(R3) ; DON'T HAVE DMO ISSUE MESSAGES BR 70$ ; BRANCH AROUND 60$: BISB #US.MUN,U.ST2(R3) ; INDICATE DEVICE IS MULTI-UNIT 70$: BIT #UF.RMV,R1 ; IS THE OTHER REMOVABLE? BNE 80$ ; IF NE YES BIS #UU.SIO,U.UTIL(R5) ; INDICATE DEVICE CAN STALL I/O BICB #US.MUN,U.ST2(R5) ; DON'T HAVE DMO ISSUE MESSAGES BR 50$ ; FINISH THE SCAN 80$: BISB #US.MUN,U.ST2(R5) ; INDICATE DEVICE IS MULTI-UNIT BR 50$ ; FINISH THE SCAN 90$: POP ; RESTORE IOP, QST, AND END PACKET .IFF ;D$$DSK MOV P.MEDI(R1),U.MEDI(R5) ; SAVE THE MEDIA ID MOV P.MEDI+2(R1),U.MEDI+2(R5) ; IT'S TWO WORDS .IFTF ;D$$DSK ; ; NOW WE CHECK OUT THE STATUS CODE AND TAKE APPROPRIATE ACTION ; CALL ENDERR ; MAP MSCP END CODE INTO AN RSX CODE PUSH <#0> ; PUT A FLAG WORD ON THE STACK MOV P.STS(R1),-(SP) ; PUT THE STATUS IN A TEMPORARY CELL BIC #^C,(SP) ; GET MAJOR CODE CMP #ST.AVL,(SP)+ ; WAS IT UNIT AVAILABLE? BNE 140$ ; NO. LEAVE THE ERROR CODE ; ; SPECIAL PROCESSING IF THE STATUS WAS UNIT-AVAILABLE ; MOV #IS.SUC,R0 ; RETURN SUCCESS AS THE STATUS CODE BIT #UU.ATN,U.UTIL(R5) ; WAS THIS GUS FROM ATTENTION MESSAGE? BEQ 170$ ; NO. JUST CONTINUE .IFF ;D$$DSK BIT #UU.BLK,U.UTIL(R5) ; SHOULD WE DO THE ONLINE? BEQ 170$ ; NO. JUST CONTINUE .IFTF ;D$$DSK INC (SP) ; MARK THE FLAG WORD AS NEEDING AN ONL BR 170$ ; GO FINISH UP .IFT ;D$$DSK 140$: TST P.STS(R1) ; WAS THE STATUS SUCCESS? BNE 170$ ; NO. FINISH UP ; ; SPECIAL PROCESSING IF THE STATUS WAS SUCCESS - UNIT ONLINE ; IF THIS IS THE GUS AFTER AN ONL, THEN REQUEST RCT AND RESTART STALL I/O ; BIT #UU.SER,U.UTIL(R5) ; WERE WE IN SERIAL MODE? BEQ 160$ ; NO. MUST HAVE BEEN AN IO.STC ;DC412 BITB #US.VV,U.STS(R5) ; IS VOLUME VALID? ;**-1 BNE 150$ ; YES. REQUEST RCT TO RUN BIT #UU.IOS,U.UTIL(R5) ; IS I/O STALLED TO THIS DEVICE? BEQ 160$ ; NO. CONTINUE ;DC412 150$: PUSH ; R1 IS A PARAMETER FOR RQRCT ;**-1 CLR R1 ; R1 = 0 TELLS RCT WE ARE INITIALIZING CALL RQRCT POP ; RESTORE R1 ; SEE IF INIT WAS STALLING I/O BIT #UU.IOS,U.UTIL(R5) ; IS I/O STALLED TO THIS DEVICE? BEQ 160$ ; NO. CONTINUE ;DC412 BIC #UU.IOS,U.UTIL(R5) ; CLEAR THE STALL I/O BIT ;**-1 BISB #US.VV,U.STS(R5) ; SET VOLUME VALID PUSH ; SAVE WORK REGISTERS MOV #T.NIOR,R0 ; SET THE I/O RESUMED MESSAGE CALL @DVMSG ; GO PRINT IT POP ; GET 'EM BACK 160$: ; REFERENCE LABEL ;DC412 ; ; IF SPECIAL ONLINE PUT STATUS CODE IN $SCERR AND CLEAR UU.SPC ; 170$: BIC #UU.ATN!UU.SER,U.UTIL(R5) ; EXIT SERIAL AND ATN STATE BIT #UU.SPC,U.UTIL(R5) ; $SCOFL? BEQ 180$ ; IF EQ, NO MOVB R0,@SCERR ; SET UP ERROR CODE FOR EXEC BIC #UU.SPC,U.UTIL(R5) ; NOLONGER SPECIAL CASE 180$: PUSH <#0> ; NO BYTE COUNT .IFF ; IF TAPE 140$: 170$: BIC #UU.ATN!UU.SER,U.UTIL(R5) ; CLEAR ATN AND SER FLAGS BIC #M.DEFM,U.CW2(R5) ; CLEAR DEFAULT FLAGS BITB #EF.EOT,P.FLGS(R1) ; EOT ENCOUNTERED ? BEQ 60$ ; NO BISB #M.EOT,U.CW2(R5) ; YES. ENCOUNTERED EOT 60$: BIT #UF.WPH,P.UNFL(R1) ; HARDWARE WRITE-PROTECTED ? BEQ 70$ ; NO BIS #M.HWL,U.CW2(R5) ; YES. HARDWARE WRITE-PROTECTED 70$: BIT #TF.PE,P.FORM(R1) ; 1600 BPI ? BEQ 80$ ; NO BIS #M.1600,U.CW2(R5) ; YES. 1600 BPI BR 90$ ; DO NOT CHECK MORE DENSITIES 80$: BIT #TF.GCR,P.FORM(R1) ; 6250 BPI ? BEQ 90$ ; NO BIS #M.6250,U.CW2(R5) ; YES. 6250 BPI 90$: ; REFERENCE LABEL CMP #ST.OFL,R0 ; UNIT OFFLINE ? BNE 110$ ; NO BIS #M.SER,U.CW2(R5) ; YES. SELECT ERROR 110$: PUSH ; SET IOSB+2 VALUE CMP I.FCN(R3),#IO.STC BEQ 120$ CMP I.FCN(R3),#IO.SMO BEQ 120$ MOV U.CW2(R5),(SP) ; VALUE TO BE USED FOR IOSB+2 120$: .ENDC ;D$$DSK CALL ENDCMO ; GO FINISH UP, AND COME BACK HERE TST (SP)+ ; SHOULD WE DO AN ONLINE? BEQ 220$ ; NO. JUST RETURN JMP ONLSIO ; GO ISSUE THE ONLINE COMMAND ; NO UNIT'S REQUIRE OP.GUS'S - LEAVE THE C1.GUS STATE 190$: MOV (R2),R3 ; R3 IS THE CST ADDRESS BIC #C1.GUS,(R3) ; LEAVE C1.GUS STATE JMP CLACMD ; GO LOOK FOR SOMETHING TO DO ; ; GO BACK TO TOP OF LOOP FOR PROCESSING MORE PACKETS 200$: CALLV PORT,PKTCH1 ; DO WE HAVE RESOURCES? ; ONLY NEED ONE CREDIT SINCE THIS ; IS AN IMMEDIATE CMD BCS 210$ ; NO RESOURCES, QUIT JMP 10$ ; WE'RE OK, GO TRY ANOTHER 210$: ADD #10,SP ; FLUSH THE UCB SCAN 220$: RETURN ; GO HOME .DSABL LSB ; DISABLE LOCAL SYMBOL DEFINITION .PAGE .SBTTL LERR - LOG AN ERROR .SBTTL CERR - LOG A CONTROLLER ERROR .IF DF E$$LOG ;+ ; **- CERR - CONTROLLER ERROR LOGGING ROUTINE ; ; THE CONTROLLER ERROR LOGGING ROUTINE WILL CAUSE THE CREATION OF AN ERROR ; LOG PACKET, COPY THE VALUES OF THE TWO I/O PAGE REGISTERS INTO THE ERROR ; LOG PACKET AND REQUEST THE ERROR LOGGING SUB-SYSTEM TO CAPTURE THE DATA. ; ; INPUTS: ; R0 = ERROR CODE (IE.FHE FOR CONTROLLER FAILURE) ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; THE ERROR (OR TIME OUT) ON THE SPECIFIED CONTROLLER IS LOGGED. ; ;- .ENABL LSB CERR: PUSH ; SAVE REGISTERS (WE NEED R0) MOV S.KRB(R4),R2 ; GET KRB ADDRESS MOV K.CSR(R2),R2 ; GET CSR ADDRESS ; ; SET UP CONTROLLER ERROR LOG PACKET ; MOV #4,C.MLNG(R3) ; SET PACKET LENGTH MOVB #-2,C.VCIX(R3) ; SET VIRTUAL CIRCUIT ID MOVB #20,C.CRED(R3) ; SET CREDIT FIELD MOV (R2),C.IP(R3) ; SAVE IP REGISTER MOV 2(R2),C.SA(R3) ; SAVE SA REGISTER MOV #C.IP,R1 ; ADJUST R1 TO ... ADD R3,R1 ; POINT TO CONTROLLER ERROR LOG PACKET ; ADJUSTED LATER TO POINT TO MLNG BR 10$ ; AND LOG ERROR PACKET ;+ ; **- LERR - UNIT ERROR LOGGING ROUTINE ; ; THE UNIT ERROR LOGGING ROUTINE WILL CAUSE THE CREATION OF AN ERROR LOG ; PACKET, COPY THE CONTENTS OF THE MSCP ERROR LOG PACKET INTO THE ERROR ; LOG PACKET AND REQUEST THE ERROR LOGGING SUB-SYSTEM TO CAPTURE THE DATA. ; ; INPUTS: ; ; R0 = COMPLETION STATUS (IS.SUC OR IE.XXX) ; R1 = CURRENT RESPONSE RING PACKET ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; THE ERROR ON THE SPECIFIED UNIT IS LOGGED. ;- LERR: PUSH ; SAVE REGISTERS 10$: CLRB S.ROFF(R4) ; ZERO OFFSET TO FIRST REGISTER OF ; ... ERRLOG PACKET MOV #MSGLNG,R2 ; GET OFFSET TO BEGINNING OF ENVELOPE ADD R1,R2 ; ADD BASE ADDRESS OF RESPONSE PACKET PUSH <(R2)> ; GET MESSAGE LENGTH ADD #-,(SP) ; ADD EXTRA FOR THE ENVELOPE CMP #RSPLNG,(SP) ; DID WE EXCEED MAXIMUM PACKET SIZE? BHIS 30$ ; IF HIS NO 20$: TST (SP)+ ; PACKET + ENVELOPE EXCEEDS MAXIMUM SIZE BR 80$ ; EXIT, CAN'T ERROR LOG IT 30$: MOV (SP),R2 ; COPY NUMBER OF BYTES TO R2 MOVB (SP)+,S.RCNT(R4) ; NUMBER OF REGISTERS TO COPY FOR ; ... ERROR LOG CLR S.PKT(R4) ; ASSUME NO IOP ACTIVE MOV CREDIT(R1),R0 ; OBTAIN MESSAGE/CREDIT FIELDS BIC #^C,R0 ; CLR ALL BUT MESSAGE TYPE FIELD CMPB #,R0 ; IS THIS RESPONSE A DATAGRAM PACKET? BEQ 40$ ; IF EQ Y MOV P.CRF+2(R1),R3 ; GET IOP ADDRESS BEQ 40$ ; NO PACKET...... NOT POSSIBLE? BITB #IP.FAK,I.FLAG(R3) ; NO. DOING AN INTERNAL I/O FUNCTION? ;DC412 BNE 40$ ; IF EQ YES ;**-1 MOV P.CRF+2(R1),S.PKT(R4) ; NO. COPY IOP ADDRESS FOR ; ... ERROR LOGGER ; IS I/O ACTIVE? BR 50$ ; NO. GO ON TO LOG IT 40$: CLR R4 ; NO. CLR R4 50$: PUSH ; SAVE R1 AGAIN MOV R2,R1 ; COPY NUMBER OF BYTES INTO R1 ; ; INTERFACE TO $LOGER: ; ; INPUTS: ; ; R1 = LENGTH OF DATA TO BE LOGGED, IN BYTES ; R4 = SCB ADDRESS (ZERO IF NO IOP) ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; C = 1 UNABLE TO LOG ERROR ; ; C = 0 ABLE TO LOG ERROR ; ; R1 = ADDRESS OF DATA AREA IN ERROR LOG PACKET ; R3 = ADDRESS OF ERROR LOG PACKET ; ; NOTE: ; ; R4 AND R5 ARE PRESERVED ; R0, R2, AND R3 MAY BE DESTROYED ; KISAR6 IS DESTROYED BY $LOGER ON 11M PLUS ; CALL @LOGER ; ATTEMPT TO LOG ERROR PACKET BCS 20$ ; EXIT IF WE CAN'T LOG THE ERROR MOV R1,R4 ; COPY R1 INTO R0 FOR DESTINATION POP ; GET POINTER TO MSCP PACKET FOR SOURCE BCS 80$ ; IF CS, UNABLE TO LOG ERROR PACKET PUSH ; SAVE DESTROYED REGISTERS ADD #MSGLNG,R2 ; OFFSET TO BEGINNING OF ENVELOPE BIC #160000,R2 ; R2 IS ADDRESS IN APR 5 RANGE BIS #120000,R2 ; MOV U.SCB(R5),R3 ; RESTORE SCB ADDRESS MOV S.PBIA(R3),R1 ; MAP TO PORT DRIVER CLR R0 ; SETUP FOR "BISB" BISB S.RCNT(R3),R0 ; NUMBER OF REGISTERS (WORDS) TO COPY MOV (SP),R3 ; RESTORE ERRORLOG PACKET ADDRESS (BIAS) CALL @BLXIO ; MOVE THE DATA MOV U.SCB(R5),R4 ; R4 IS THE SCB MOV S.PBIA(R4),@KISR6 ; MAP APR 6 TO PORT DRIVER MOV S.PBIA(R4),@#KINAR6 ; KERNAL DATA POP ; GET MAPPING BIAS FOR ERRLOG PACKET POP ; RESTORE REGISTER MOV (SP),R0 ; GET STATUS WHICH CAME IN R0 TST S.PKT(R4) ; IS I/O ACITVE? BNE 70$ ; IF NE YES CLR R4 ; NO. CLR R4 CLR R2 ; DON'T FORGET R2 ; ; ; INTERFACE TO $FNERL: ; ; INPUTS: ; ; R0 = FIRST I/O STATUS WORD ; R2 = STARTING AND FINAL ERROR RETRY COUNTS ; R3 = ADDRESS OF ERROR LOG PACKET (BIAS IF MPLUS) ; R4 = SCB ADDRESS (ZERO IF NO IOP) ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; THE SPECIFIED ERROR LOG PACKET IS LOGGED ; ; NOTE: ; ; R4 AND R5 ARE PRESERVED ; R1, R2, AND R3 MAY BE DESTROYED ; 70$: CALL @FNERL ; FINISH LOGGING THIS ERROR LOG PACKET 80$: POP ; RESTORE REGISTERS MOV S.PBIA(R4),@KISR6 ; MAP APR 6 TO PORT DRIVER MOV S.PBIA(R4),@#KINAR6 ; KERNAL DATA RETURN .DSABL LSB .ENDC .PAGE .SBTTL MAPD - COROUTINE TO MAP THE PORT .SBTTL SAVREG - COROUTINE TO SAVE R0-R3 ;+ ; **-MAPD-SAVE AND LATER RESTORE APR 6 ; R0 IS DESTROYED ;- MAPD: POP ; REMEMBER WHERE TO RETURN PUSH <@KISR6> ; SAVE APR 6 MOV S.PBIA(R4),@KISR6 ; MAP APR 6 TO PORT DRIVER PUSH <@#KINAR6> ; SAVE INSTRUCTION SPACE APR 6 MOV S.PBIA(R4),@#KINAR6 ; FOR I/D SYSTEMS MAP BOTH I AND D CALL (R0) ; CALL CALLER BACK AS A CO-ROUTINE ; ; COROUTINE RETURN POINT ; POP <@#KINAR6> ; RESTORE INSTRUCTION SPACE APR 6 POP <@KISR6> ; RESTORE PREVIOUS APR6 MAPPING RETURN ;+ ; **-SAVREG-SAVE AND LATER RESTORE R0-R3 ;- SAVREG: PUSH ; STORE R0 TEMPORARILY ON THE STACK MOV 2(SP),R0 ; GET RETURN ADDRESS IN R0 POP <(SP)> ; MOVE ORIGINAL R0 OVER RETURN ADDRESS PUSH ; SAVE R1-R3 AND THE RETURN ADDRESS MOV 10(SP),R0 ; RESTORE R0 CALL @(SP)+ ; CALL BACK THE CALLER AS A COROUTINE ; ; COROUTINE RETURN POINT ; POP ; RESTORE THE REGISTERS RETURN .PAGE .SBTTL CMDONL - ISSUE ONLINE COMMANDS ;+ ; **-CMDONL- DEVICE ONLINE ; ; CONTROL IS PASSED TO THIS POINT WHEN AN ONLINE REQUEST IS ISSUED BY THE USER, ; AS IN AN IO.STC COMMAND ; ; INPUTS: ; ; R0 = FUNCTION TABLE ENTRY ; R1 = ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; IF C1.ONL IS CLEARED THEN ; ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ;- ONLSIO: MOV (R2),R3 ; MAKE SURE WE HAVE THE CST CALL PIOPAL ; GO GET A PSEUDO IOP CMDONL: MOV #ONLFUN,R0 ; GET TABLE ENTRY FOR OP.ONL BIS #UU.SER,U.UTIL(R5) ; SERIAL MODE FOR THIS ONE CALL CMDCOM ; SET UP COMMAND PACKET .IF DF T$$APE ; ; TAPE SET UP DENSITY AND (USER SETTABLE BITS?) ; BIT #UU.BLK,U.UTIL(R5) ; ONLY 1 DENSITY SUPPORTED? BNE 40$ ; YES. USE 0 (CONTROLLER PICKS DENSITY) BIT #M.1600,I.PRM(R3) ; YES. 1600 BPI BEQ 30$ ; NO BIS #TF.PE,P.FORM(R1) ; 1600 BPI BR 40$ ; IGNORE NEXT DENSITY CHECK 30$: BIT #M.6250,I.PRM(R3) ; YES. 6250 BPI BEQ 40$ ; NO BIS #TF.GCR,P.FORM(R1) ; 6250 BPI ? 40$: .ENDC ;T$$APE PUSH <#CLACMD> ; TRY TO ISSUE MORE COMMANDS CALL CMDSEN ; SEND THE COMMAND TO THE CONTROLLER ; ; PROCESS END PACKET FOR OP.ONL - INPUTS: ; ; R1 = END PACKET ADDRESS ; R2 = QST ADDRESS ; R3 = P/IOP ARDDESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; FOR DISK SAVE SOME INFORMATION IN THE UCB EXTENSION ; BIC #UU.SER,U.UTIL(R5) ; LEAVE SERIAL MODE .IF DF D$$DSK ; ; SAVE INFORMATION IN UCB EXTENSION ; PUSH ; SAVE END PACKET, QST, AND IOP MOV #,R0 ; SET NUMBER OF BYTES TO MOVE MOV R1,R2 ; COPY MSCP PACKET POINTER TO R2 ADD #P.UNSZ,R2 ; UPDATE OFFSET INTO MSCP PACKET MOV @KISR6,R1 ; GET PACKET'S BASE ADDRESS SUB #20000,R2 ; BIAS IT PROPERLY MOV U.UC2X(R5),R3 ; GET DESTINATION APR6 BIAS MOV #X.UNSZ+140000,R4 ; GET DESTINATION DISPLACEMENT CALL @BLXIO ; MOVE THE DATA MOV 4(SP),R2 ; RETRIEVE MSCP PACKET POINTER MOV U.SCB(R5),R4 ; RESTORE SCB ADDRESS MOV P.UNSZ(R2),U.CW3(R5) ; SET UP THE MAX LBN ... MOVB P.UNSZ+2(R2),U.CW2(R5) ; AND THE HIGH ORDER PART ;DC412 ;+ ;DC412 ; Handle 32-bit LBN access in this section. If the device is larger ;DC412 ; than 24-bits, we will use the full word for U.CW2, otherwise we will ;DC412 ; only allow a maximum of 24 bits of storage, to insure we match what ;DC412 ; the executive will support ;DC412 ;- ;DC412 BIC #DV.32B,U.CW1(R5) ; INSURE WE DON'T LOOK LIKE 32 BITS ;DC412 TSTB P.UNSZ+3(R2) ; IS THIS TOO BIG? ;DC412 BEQ 55$ ; IF EQ, NOPE, USE ACTUAL ;DC412 TSTB @FMSK6 ; EXECUTIVE SUPPORT INCLUDED? ;DC412 BMI 50$ ; IF MI, YES, CONTINUE ;DC412 MOV #377,U.CW2(R5) ; SET SIZE TO MAXIMUM AVAILABLE ;DC412 MOV #-1,U.CW3(R5) ; BOTH HALVES ;DC412 BR 55$ ; DONE WITH LOADING ;DC412 50$: MOV P.UNSZ+2(R2),U.CW2(R5) ; ... FOR PROPER OPERATION ;DC412 BIS #DV.32B,U.CW1(R5) ; SHOW 32 BIT DEVICE ;DC412 55$: ; REFERENCE LABEL ;DC412 POP ; RESTORE IOP, QST, AND END PACKET ;**-1 .ENDC ;D$$DSK BIT #UU.SPC,U.UTIL(R5) ; IS THIS A SPECIAL ONLINE ;DC521 BNE 57$ ; IF SO, ALWAYS GUS FOR SCERR ;DC521 ;DC521 MOV P.STS(R1),R0 BIC #^C,R0 ; ISOLATE MAJOR CODE BNE 70$ ; IF NOT SUCCESS, ST.SUC, SKIP ; ; UNIT IS NOW ONLINE, FIND OUT ABOUT IT BY DOING AN OP.GUS ; 57$: MOV (R2),R0 ; R0 IS THE CST ;DC521 BIS #C1.GUS,(R0) ; ENTER C1.GUS STATE ;**-1 ; STATE= SERIAL, GUS, RDY BIS #UU.SER!UU.GUS!UU.RDY,U.UTIL(R5) BICB #US.SPU,U.STS(R5) ; CLEAR SPINNING UP BIT .IF DF T$$APE ; ; IF TAPE AND IF (IO.STC!IO.SMO) THEN LEAVE THE POWERFAIL STATE ; CMP I.FCN(R3),#IO.STC BEQ 60$ CMP I.FCN(R3),#IO.SMO BNE 70$ 60$: BICB #US.PWF,U.STS(R5) .ENDC ;T$$APE 70$: PUSH ; SAVE R1 MOV P.STS(R1),R1 ; R1 IS COMPLETION CODE CMP #ST.VOL,R1 ; IS IT A MEDIA ERROR BNE 80$ ; NO. CONTINUE MOV #IE.DNR&377,R0 ; DEVICE NOT READY BR 110$ ; JOIN COMMON CODE 80$: CMP #ST.OFL,R1 ; MSCP OFFLINE (NO SUCH UNIT)? BNE 90$ ; NO. CONTINUE MOV #IE.IDU&377,R0 ; ILLEGAL DEVICE OR UNIT BR 100$ ; JOIN COMMON CODE 90$: MOV #IS.SUC&377,R0 ; ASSUME SUCCESS BIC #^C,R1 ; ISOLATE MAJOR CODE IS ST.SUC BEQ 110$ ; IF SUCCESS OK .IF DF D$$DSK CMP #ST.MFE,R1 ; IS IT MEDIA FORMAT ERROR? BNE 95$ ; NO. CONTINUE MOV #IE.BCC&377,R0 ; SET UP FOR MEDIA FORMAT ERROR BR 110$ ; JOIN COMMON CODE .ENDC ;D$$DSK 95$: MOV #IE.OFL&377,R0 ; ELSE SET TO DEVICE OFFLINE 100$: .IIF NDF R$$MPL&T$$APE BISB #US.OFL,U.ST2(R5) ; RSX-11M DISK DRIVER ONLY 110$: POP ; RESTORE R1 PUSH <#0> ; ZERO BYTE COUNT FOR ONLINE COMMANDS CALLR ENDCOM ; .PAGE .SBTTL PIOPAL - ALLOCATE A PSEUDO IOP ;+ ; **-PIOPAL-ROUTINE TO ALLOCATE A PSEUDO IOP ; ; THIS ROUTINE WILL ALLOCATE A PSEUDO IOP FROM PRIMARY POOL ; ; INPUTS: ; ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R0-R1 ARE DESTROYED ; R2-R4-R5 ARE PRESERVED ; R3 = PIOP ADDRESS IF SUCESSFULLY ALLOCATED ; C=0 PIOP IS SUCESSFULLY ALLOCATED ; C=1 PIOP CANNOT BE ALLOCATED ;- PIOPAL: MOV #I.LGTH,R1 ; SIZE OF PIOP (BYTES) TO ALLOCATE PUSH ; SAVE R2 CALL @ALOCB ; ALLOCATE PIOP FROM POOL POP ; RESTORE R2 BCS 30$ ; CANNOT ALLOCATE PIOP - GET OUT MOV R0,R3 ; PUT IOP ADD IN R3 PUSH <#I.LGTH/2> ; PACKET LENGTH 20$: CLR (R0)+ ; CLEAR A WORD AT A TIME DEC (SP) ; ONE LESS WORD TO CLEAR BGT 20$ ; GO DO ENTIRE PACKET TST (SP)+ ; CLEAN UP THE STACK MOVB #IP.FAK,I.FLAG(R3) ; SET TO 1 TO INDICATE PIOP ;DC412 MOV R5,I.UCB(R3) ; SET UP UCB ADDRESS ;**-1 CLC ; CLEAR CARRY BR 40$ ; AND EXIT 30$: MOV #177773,R3 ; PUT A BAD ADDRESS IN R3 SINCE NO ; POOL AVAILABLE SEC ; SET CARRY 40$: RETURN .PAGE .SBTTL PIOPDE - DEALLOCATE A PSEUDO IOP ;+ ; **-PIOPDE-ROUTINE TO DEALLOCATE A PSEUDO IOP ; ; THIS ROUTINE WILL DEALLOCATE A PSEUDO IOP. IF THE ; PIOP IS FROM POOL, THEN DEALLOCATE IT FROM SYSTEM POOL, ; ELSE IT IS FROM THE CST SO JUST MARK THE FIRST WORD AS -1 ; TO INDICATE THAT IT IS FREE. ; ; INPUTS: ; ; R1 = PIOP ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; ; OUTPUTS: ; ; R0-R1 DESTROYED ; R2-R5 ARE PRESERVED ; ;- PIOPDE: PUSH ; SAVE R2,R3 MOV R1,R0 ; ADD OF PIOP IN POOL TO DEALLOCATE MOV #I.LGTH,R1 ; NUMBER OF BYTES TO DEALLOCATE CALL @DEACB ; DEALLOCATE PIOP POP ; RESTORE R3,R2 RETURN .PAGE .IF DF,D$$DSK .SBTTL RECSIO - CONTINUE RECOVERY FROM A CONDITION THAT REQUIRED A RE-SYNCH ;+ ; **-RECSIO-CONTINUE RECOVERY FROM A CONDITION THAT REQUIRED A RE-SYNCH ; ; AFTER ALL UNITS ARE BROUGT BACK ONLINE FROM THE TIMEOUT ROUTINE ; THEN ALL OUTSTANDING I/O IS RE-ISSUED AND C1.REC STATE IS CLEARED ; ; INPUTS: ; ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2,R3,R4 PRESERVED ; R5 IS A UCB ADDRESS ;- RECSIO: ; PROPER OPERATION OF THIS CODE DEPENDS ON THE FACT THAT THIS DRIVER ; ALWAYS TRYS TO START MORE COMMANDS AFTER IT COMPLETES PROCESSING ; ANY RECEIVED END PACKETS. ; ; RECOVERY INVOLVES THREE STAGES AND IS CONTROLLED BY THE STATE ; BITS C1.R1, C1.R2 AND C1.REC. THE THREE BITS ARE RELATED TO ; THREE PARTS OF RECOVERY; ISSUING ONLINES, RETRYING ONLINES ; AND RE-ISSUING OUTSTANDING COMMANDS. ; ; C1.R1 IS SET TO INDICATE THAT IT IS TIME TO TRY AND BRING ; "SPINNING UP" UNITS (US.SPU SET) BACK ONLINE. C1.R1 IS ; CLEARED AFTER UNITS ARE MARKED AS NEEDING TO BE BROUGHT ; ONLINE. IF, AFTER ALL ONLINES COMPLETE, THERE ARE STILL ; UNITS THAT DIDN'T COME READY THE DRIVER WILL SET A ; TIMEOUT. WHEN THE TIMEOUT COMES DUE C1.R1 WILL BE SET ; AND CONTROL WILL TRANSER HERE WHERE WE WILL TRY TO ONLINE ; THE UNITS AGAIN. THIS BEHAVIOR IS REPEATED UNTIL EITHER ; ALL UNITS ARE READY OR RETRYS ARE EXHAUSTED. ; ; IF POSSIBLE IT WOULD BE BETTER TO HAVE LIMITLESS RETRYS ; FOR THE SYSTEM DISK. THIS IS NOT CURRENTLY THE CASE. ; ; C1.R2 REMAINS SET AS LONG AS THERE ARE STILL UNITS SPINNING ; UP. ; ; C1.REC REMAINS SET UNTIL ALL OUTSTANDING COMMANDS HAVE BEEN ; RE-ISSUED AND COMPLETED. THE OLDEST COMMAND MUST COMPLETE ; BEFORE SUBSEQUENT OUTSTANDING COMMANDS ARE RE-ISSUED AND ALL ; RE-ISSUED COMMANDS MUST COMPLETE BEFORE NEW I/O MAY BE STARTED. ; ; IF C1.R1 IS SET THEN MARK UNITS THAT NEED TO COME ONLINE ; AND GOTO ONLSIO TO START THE COMMANDS ; BIT #C1.R1,(R3) BEQ 40$ ; THIS SECTION DONE ONLY IF C1.R1 SET BIC #C1.R1,(R3) ; CLEAR C1.R1 SO THAT THIS WILL ; ONLY BE DONE ONCE. MOV #SCUCB,-(SP) ; PUSH "SCAN UCB'S" ROUTINE ON THE STACK 10$: CALL @(SP)+ ; CALL THE CO-ROUTINE BCS 30$ ; IF CS, ALL DONE BITB #US.SPU,U.STS(R5) ; IS THIS UNIT SPINNING UP BEQ 10$ ; IF NOT, GO AGAIN BIT #UU.SER,U.UTIL(R5) ; ONLINE IN PROGRESS (FROM ATTEN. MSG)? BNE 10$ ; IF SO, GO AGAIN INC U.CNT(R5) ; COUNT THIS ONLINE ATTEMPT CMP U.CNT(R5),#120. ; RETRY COUNT EXCEEDED? BLE 20$ ; IF LE, NO. TRY AGAIN BICB #US.SPU,U.STS(R5) ; RETRYS EXHAUSTED, CLEAR SPINNING UP CLR U.CNT(R5) ; AND RETRY COUNT. BIS #UU.ABO,U.UTIL(R5) ; ABORT ALL I/O FOR THIS UNIT BR 10$ ; TRY NEXT UNIT 20$: BIS #UU.SER!UU.GUS!UU.ATN,U.UTIL(R5) ; GET UNIT STATUS, AND THEN ONL BR 10$ ; GO THROUGH LOOP 30$: BIS #C1.GUS,(R3) ; SET GET UNIT STATUS STATE JMP GUSSIO ; ; AT THIS POINT C1.R1 IS CLEAR BUT C1.R2 MAY BE SET. C1.R2 WILL ; BE CLEARED WHEN ALL UNITS HAVE BECOME READY AND HAVE BEEN BROUGHT ; BACK ONLINE OR WHEN RETRYS HAVE BEEN EXHAUSTED. THIS CONDITION ; IS TRUE WHEN US.SPU IS CLEAR FOR ALL UNITS. ; ; THIS SECTION OF CODE WILL SET A TIMEOUT IF ANY UNITS HAVE ; FAILED TO SPIN UP. AT THE END OF THE TIMEOUT CONTROL WILL ; TRANSFER TO RECSIO WITH C1.R1 SET SO THAT MORE ONLINES WILL ; BE TRYED. ; 40$: BIT #C1.R2,(R3) ; IN SECOND STAGE OF RECOVERY? BEQ 90$ ; IF EQ, NO. TRY THIRD STAGE BIC #C1.R2,(R3) ; ASSUME ALL UNITS ARE READY MOV #SCUCB,-(SP) ; PUSH "SCAN UCB'S" ROUTINE ON THE STACK 50$: CALL @(SP)+ ; CALL THE CO-ROUTINE BCS 60$ ; IF CS, ALL DONE BITB #US.SPU,U.STS(R5) ; IS THIS UNIT SPINNING UP BEQ 50$ ; IF NOT, GO AGAIN BIS #C1.R2,(R3) ; SET C1.R2, NOT DONE YET BR 50$ ; TRY NEXT UNIT 60$: BIT #C1.R2,(R3) ; DONE? BEQ 90$ ; IF EQ, YES. DO NEXT STAGE TST C.OLHD(R3) ; WAITING FOR I/O TO COMPLETE? BEQ 70$ ; IF YES. EXIT ; LATER AFTER END PACKETS ; ARE COMPLETED WE WILL BE CALLED AGAIN ; AT WHICH TIME WE CAN SET A TIMEOUT ; FOR ONLINE RETRYS RETURN 70$: TST S.BSYU(R4) ; IS A UNIT BUSY ALREADY? BNE 80$ ; IF NE, YES WE MUST BE WAITING ; FOR A TIMEOUT SO DON'T RESET IT MOV R5,S.BSYU(R4) ; ELSE, SET A UNIT BUSY BISB #US.BSY,U.STS(R5) MOVB #2,S.CTM(R4) ; SET A 2 SECOND TIMEOUT 80$: RETURN ; ; AT THIS POINT C1.R1 AND C1.R2 MUST BE CLEAR AND IT IS THEREFORE TIME ; TO RE-ISSUE I/O. ; 90$: BIC #C1.REC,(R3) ; ASSUME WE ARE FINISHED MOV C.REQU(R3),R1 ; R1 IS THE FIRST IOP FROM C.REQU ; ANY I/O TO RESTART? BEQ 130$ ; NO. THEN SEE IF WE ARE DONE? BIS #C1.REC,(R3) ; WE ARE NOT DONE YET CMP R1,C.REDO(R3) ; IS THIS THE OLDEST AT TIME OF FAIL? BEQ 110$ ; IF YES. GO START IT TST C.OLHD(R3) ; WE KNOW THE OLDEST HAS STARTED BUT ; ARE WE STILL WORKING ON IT? BEQ 100$ ; IF EQ, NO. SO GO CLEAR C.REDO CMP C.OLHD(R3),C.REDO(R3) ; ARE WE STILL WORKING ON IT? BEQ 150$ ; YES. SO WAIT FOR IT TO FINISH 100$: CLR C.REDO(R3) ; OTHERWISE WE MUST HAVE FINISHED THE ; OLDEST COMMAND SO ITS TIME TO ; FORGET IT. ; ; START PROCESS OF RE-ISSUING AN I/O ; R1 IS THE IOP ; R3 IS THE CST ; R4 IS THE SCB ; 110$: MOV I.UCB(R1),R5 ; R5 IS THE UCB ADDRESS MOV R3,R0 ADD #C.REQU,R0 ; R0 IS THE POINTER TO THE QUEUE CALL @QRMVA ; REMOVE THE FIRST ENTRY BIT #UU.ABO,U.UTIL(R5) ; DID THIS UNIT FAIL TO BECOME READY? BEQ 120$ ; IF EQ, NO. GO RE-ISSUE THE I/O ; OTHERWISE COMPLETE IT AS IE.DNR MOV R1,R3 ; R3 IS THE IOP MOV #IE.DNR&377,R0 ; R0 IS IE.DNR (DEVICE NOT READY) CLR R1 ; R1 IS A ZERO BYTE COUNT CALL ENDCM1 ; COMPLETE THE I/O BR 90$ ; GO TRY TO START ANOTHER I/O 120$: MOV S.QST(R4),R2 ; RESTORE THE QST JMP CMDRED ; RESTART ENTRY IN CMDSIO ; ; WE ARE NOT DONE UNTIL I/O'S HAVE COMPLETED ; 130$: TST C.OLHD(R3) ; STILL WORKING ON COMMANDS? BNE 150$ ; YES. JUST EXIT ; ELSE WE ARE DONE CLRB S.CTM(R4) ; STOP TIMER JUST IN CASE MOV S.BSYU(R4),R1 ; GET UCB ADDRESS BEQ 140$ ; IF NONE SKIP BICB #US.BSY,U.STS(R1) ; CLEAR BUSY BIT CLR S.BSYU(R4) ; CLEAR BUSY UNIT IN SCB 140$: CLR C.REDO(R3) ; FORGET ABOUT OLDEST COMMAND IF IT WAS ; THE ONLY COMMAND CALLR CLACMD ; START ANY PENDING I/O 150$: BIS #C1.REC,(R3) ; STILL RECOVERING RETURN .PAGE .SBTTL RQRCT - REQUEST REPLACEMENT CONTROL TASK ;+ ; **- RQRCT - REQUEST REPLACEMENT CONTROL TASK ROUTINE ; ; THE REQUEST THE REPLACEMENT CONTROL TASK ROUTINE IS CALLED ; TO INITIALIZE THE SPECIFIED UNIT OR TO REPLACE A BAD BLOCK ON ; THE SPECIFIED UNIT. ; ; INPUTS: ; ; R1 = ADDRESS OF CURRENT RESPONSE RING PACKET IF REPLACEMENT ; OR ELSE ZERO IF INITIALIZATION ; R2 = QST ADDRESS ; R3 = IOP ADDRESS ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; THE REPLACEMENT CONTROL TASK IS REQUESTED TO REPLACE ; THE BAD BLOCK ON THE SPECIFIED UNIT. ; ;- RQRCT: ; REF LABEL PUSH ; SAVE R0-R3 MOV U.UC2X(R5),@KISR6 ; MAP SECOND UCB EXTENSION MOV X.UNFL+140000,R1 ; RETRIEVE UNIT FLAGS MOV X.RCTS+140000,R0 ; RETRIEVE RCT SIZE MOV S.PBIA(R4),@KISR6 ; RESTORE PORT MAPPING TST R0 ; DOES IT EVEN HAVE AN RCT? BEQ 20$ ; NO. JUST EXIT BIT #UF.RPL,R1 ; CONTROLLER INITIATED BAD BLOCK REPLACEMENT? BNE 20$ ; IF NE YES 5$: TST @RCTPT ; IS RCT INSTALLED? ;DC412 BNE 40$ ; IF NE YES ;**-1 MOV #T.NRCT,R0 ; SET MESSAGE "REPLACEMENT CONTROLL TASK ... ; ... NOT INSTALLED" 10$: CALL @DVMSG ; GO PRINT IT 20$: MOV 4(SP),R1 ; RETREIVE R1 ;DC412 .IF DF,D$$PRT ; PARTITIONED DRIVES ;DC412 BNE 25$ ; NOPE, UPDATE THE ERROR STATUS ;DC412 BIT #UU.PTV,U.UTIL(R5) ; PARTITION TABLE VALID? ;DC412 BNE 30$ ; IF NE, YES, CONTINUE ;DC412 TST @RCTPT ; RCT INSTALLED? ;DC412 BEQ 30$ ; IF EQ, NOPE ... ;DC412 CMP @RCTPT,I.TCB(R3) ; IS THIS FROM RCT... ;DC412 BEQ 30$ ; IF EQ, CONTINUE ;DC412 BR 50$ ; CONTINUE ON ... ;DC412 .IFF ;DF,D$$PRT ;DC412 BEQ 30$ ; IF EQ, YES, DON'T CHANGE ERROR CODE ;DC412 .ENDC ;DF,D$$PRT ;DC412 25$: MOV #IE.BBE&377,6(SP) ; SET BAD BLOCK ERROR IN STORED R0 ;DC412 30$: SEC ; SET CARRY TO INDICATE NO NEED TO REQUE;**-3 BR 90$ ; EXIT 40$: ; REF LABEL CMP @RCTPT,I.TCB(R3) ; IS THE I/O FROM RCT? BNE 50$ ; NO. REQUEST RCT CLR R0 ; GET A WORKING REGISTER MOV 4(SP),R1 ; GET END PACKET BISB P.FLGS(R1),R0 ; GET FLAGS SWAB R0 ; PUT THE FLAGS IN THE HIGH BYTE BIS R0,6(SP) ; SET THE FLAG BITS IN THE I/O STATUS ON STACK BR 30$ ; EXIT 50$: MOV #12.,R1 ; SET LENGTH OF BLOCK NEEDED CALL @ALOCB ; GET A CORE BLOCK BCC 60$ ; IF CC GOT ONE MOV #T.NUER,R0 ; SET MESSAGE BR 10$ ; GO ON 60$: MOV R0,R3 ; SET ADDRESS OF MESSAGE BLOCK TST (R0)+ ; POINT TO SECOND WORD IN BLOCK MOV 4(SP),R1 ; DO WE HAVE AN INITIALIZATION REQUEST? BEQ 70$ ; IF EQ YES MOV P.CRF+2(R1),(R0)+ ; NO. INSERT IOP ADDRESS (REPLACEMENT ; REQUIRED INDICATOR) MOV R5,(R0)+ ; INSERT UCB ADDRESS MOV P.FBBK+2(R1),(R0)+ ; INSERT HI LBN TO BE REPLACED MOV P.FBBK(R1),(R0)+ ; INSERT LO LBN TO BE REPLACED MOV P.STS(R1),(R0) ; GIVE EVENT CODE TO RCT BR 80$ ; AND CONTINUE 70$: CLR (R0)+ ; INSERT INITIALIZATION INDICATOR MOV R5,(R0)+ ; INSERT UCB ADDRESS CLR (R0)+ ; CLR LO LBN POSITION CLR (R0)+ ; CLR HI LBN POSITION CLR (R0) ; NO EVENT CODE TO RCT (INITIALIZATION) .IF DF,D$$PRT ; PARTITIONED DRIVES? ;DC412 BIT #UU.SPC,U.UTIL(R5) ; SPECIAL ONLINE? ;DC412 BNE 80$ ; YES, SAVE HAS IT UNDER CONTROL ;DC412 BIS #UU.RCT,U.UTIL(R5) ; LOCK UP THE DRIVE OTHERWISE FOR RCT ;DC412 .ENDC ;DF,D$$PRT ; ;DC412 80$: MOV R3,R1 ; COPY ADDRESS OF MESSAGE BLOCK MOV @RCTPT,R0 ; PICK UP RCT'S TCB ADDRESS CALL @EXRQF ; REQUEST RCT TO RUN CLC ; CLR CARRY TO INDICATE RCT REQUESTED 90$: POP ; RESTORE R3,R2,R1 AND R0 RETURN .ENDC ;D$$DSK .PAGE .SBTTL SCUCB - GET ADDR OF NEXT UCB ON CONTROLLER ;+ ; ** - SCUCB - SCAN UCB'S ASSOCIATED WITH SPECIFIED CONTROLLER (SCB ADDRESS) ; ; ; INPUTS: ; ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; ; R1 = DESTROYED ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; CARRY CLEAR=UCB FOUND ; CARRY SET=NO MORE UCBS ;- SCUCB: POP ; RETRIEVE RETURN ADDRESS PUSH ; SAVE R5 AND R3 MOV U.SCB(R5),R3 ; GET SCB ADDRESS MOV S.KRB(R3),R3 ; GET ADDRESS OF KRB ADD K.OFF(R3),R3 ; OFFSET TO THE UCB TABLE 10$: CMP #-1,(R3) ; ARE WE AT THE END OF THE UCB TABLE? BEQ 20$ ; IF EQ YES MOV (R3)+,R5 ; GET ADDRESS OF NEXT UCB, IS THERE ONE? BEQ 10$ ; IF EQ NO MOV U.SCB(R5),R4 ; GET SCB ADDRESS FOR THIS UNIT PUSH ; SAVE UCB TABLE POINTER MOV 2(SP),R3 ; RETRIEVE CALLER'S R3 CLC ; CLR CARRY TO SHOW WE FOUND ONE CALL (R1) ; CALL THE CALLER BACK POP ; GET RETURN ADDRESS AND POINTER TO NEXT UCB ENTRY BR 10$ ; TRY THE NEXT UCB 20$: ; REF LABEL POP ; RESTORE ORIGINAL R3 AND R5 MOV U.SCB(R5),R4 ; GET SCB ADDRESS FOR THIS UNIT SEC ; SET CARRY TO SHOW THE END JMP (R1) ; EXIT .PAGE .SBTTL TMOGCS - PROCESS END PACKET FROM OP.GCS ;+ ; **-TMOGCS-RESPOND TO RECEIPT OF END PKT FOR OP.GCS COMMAND ; ; INPUTS: ; ; R1 = END PACKET ADDRESS ; R2 = QST ADDRESS ; R3 = CST ADDRESS ; ; OUTPUTS: ; ; IF THE COMMAND IS MAKING PROGRESS OR HAS COMPLETED THEN DO NOTHING ; OTHERWISE INITIATE A RE-SYNCHRONIZATION ;- TMOGCS: BIC #C1.TMO,(R3) ; INDICATE OP.GCS COMPLETED MOV P.OTRF+2(R1),R0 ; GET IOP ADDRESS CMP R0,C.OLHD(R3) ; IS IT THE SAME COMMAND? BNE 30$ ; NO. THE COMMAND MUST HAVE FINISHED MOVB I.FLAG(R0),R0 ; GET SEQUENCE NUMBER ;DC412 BIC #^C<17>,R0 ; CLEAR ALL BUT THE LOW FOUR BITS ;**-1 CMP R0,P.OTRF(R1) ; BOTH REFERENCE NUMBERS THE SAME? BNE 50$ ; NO. COMMAND MUST HAVE FINISHED TST P.CMST(R1) ; REF NUMBER ZERO? BNE 10$ ; NO. WE HAVE TO SEE IF IT MADE PROGRESS TST P.CMST+2(R1) ; HOW ABOUT THE OTHER REF NUMBER? BEQ 50$ ; NO. COMMAND MUST HAVE FINISHED 10$: CMP P.CMST+2(R1),C.CMST+2(R3) ; DID IT MAKE PROGRESS? BHI 20$ ; NO. TIME OUT ERROR BLO 30$ ; YES CMP P.CMST(R1),C.CMST(R3) ; HIGH WORD WAS EQUAL, CHECK LOW WORD BLO 30$ ; IF LOWER THEN IT DID MAKE PROGRESS 20$: CALLV PORT,PKTDR ; DEALLOCATE END PACKET JMP TMOERR ; JMP TO TIME OUT ERROR 30$: MOV P.CMST(R1),C.CMST(R3) ; COMMAND STATUS - PART 1 MOV P.CMST+2(R1),C.CMST+2(R3); COMMAND STATUS - PART 2 50$: ; REFERENCE LABEL MOVB S.ITM(R4),S.CTM(R4) ; RESET TIMEOUT COUNT CALLV PORT,PKTDR ; DEALLOCATE THE PACKET RETURN .END